笔记(十一)

本文深入探讨了内部函数、闭包和装饰器的概念及应用。闭包特征包括访问外部函数变量,而装饰器是在闭包基础上,将函数作为参数,用于功能增强。文中通过实例展示了如何使用非本地和全局变量,并解释了装饰器在用户登录状态检查等场景的应用。最后,详细阐述了装饰器的工作原理及其在实际代码中的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 内部函数  闭包和装饰器的基础

思想:内部函数主要是为了实现闭包,而装饰器又是基于闭包

           内部函数-闭包-装饰器是一个连贯的知识点

函数里面又声明的函数,声明的函数就是内部函数

特点

1.可以访问外部函数的变量

2.内部函数可以修改外部函数的可变类型的变量(如:list1)

3.内部函数修改全局的不可变变量时,需要在内部函数声明: global 变量名

   内部函数修改外部函数不可变变量是,需要在内部函数中声明:nonlocal 变量名

def func():
    n=100  #局部变量
    list1 = [9,20,3,4]
    #声明内部函数
    def inner_function():
        nonlocal n
        #对list1里面的元素进行加n操作
        for index,i in enumerate(list1):
            list1[index]=i+n
            #内部函数可以访问局部变量
        list1.sort()
        n+=1
    #函数单纯定义没有任何意义,需要调用一下内部函数
    inner_function()
    print(list1)
    print('打印老大n',n)
func()
'''
打印老大n 101
'''

用debug调试,func()处设置断点

a=100 #全局变量
def func():
    b=100  #局部变量
    def inner_func():
        c=88
        #尝试打印a,b,c,的值
        print(a,b,c)
    inner_func()
func()
'''
100 100 88
'''
a=100 #全局变量
def func():
    b=100  #局部变量
    def inner_func():
        global a
        nonlocal b
        c=88
        #尝试修改
        c+=12
        b+=12
        a+=10
        #尝试打印a,b,c,的值
        print(a,b,c)
    #调用内部函数
    inner_func()
    print(locals())
func()
'''
110 112 100
{'inner_func': <function func.<locals>.inner_func at 0x000002373BC9A310>, 'b': 112}
'''

locals() 查看当前函数中声明的内容有哪些,以字典形式输出

globals()查看全局变量有哪些,以字典形式输出,里面有一些系统的键值对

闭包

在函数中提出的概念

条件

1.外部函数中定义了内部函数

2.外部函数有返回值

3.返回的值是内部函数(不能加括号,加括号表示调用)

4.内部函数引用了外部函数变量的值

格式

'''
def 外部函数():
    ...
    def 内部函数():
        ...
    return 内部函数
'''

例子

#外部访问内部函数
def func():
    a=100
    def inner_func():
        b=99
        print(a,b)
    return inner_func  #内部函数通过return扔出
x=func()
print(x)
#x就是内部函数,x()表示调用函数
x()
'''
<function func.<locals>.inner_func at 0x00000184D1A1A310>
100 99
'''
def func(a,b):
    c=10
    def inner_func():
        s=a+b+c
        print('结果:',s)
    return inner_func
#调用func
ifunc=func(6,9) #ifunc就是inner_func
#调用返出来的内部函数
ifunc()
'''
结果: 25
'''

——————分割线——————

装饰器   依赖闭包   闭包的基础上多一个条件:函数作为外层函数的参数

应用场景:加入购物车、付款、修改地址……都要判断用户的登录状态,依赖装饰器

引入

def func(num):
    a=100
    def inner_func():
        nonlocal a   #修改局外变量
        nonlocal num #传进来的参数num也可以修改
        num+=1
        for i in range(num):
            a+=1
        print('修改后a的值:',a)
    return inner_func   #此处千万不要带括号
#调用func
f = func(5)  #func返回的是内部函数
f()  #f变为inner_func,()进行调用
'''
修改后a的值: 105
'''

地址引用

def test():  #声明函数
    print('---test---')
t=test #函数test赋值给t
#类比
a=10   #声明整型变量
b=a    #a值赋给b
test()
t()    #即调用test
'''
---test---
---test---
'''

  

def func(x):
    print('--->',x)
a=10
func(a)
'''
---> 10
'''

def test():  #声明函数
    print('---test---')
t=test
def func(f):
    print(f)
    f()   #0x00000199AB91F040  去这个地方调用f
func(test)  #f=test,同t
'''
<function test at 0x00000199AB91F040>
---test---
'''

整体上只有两个函数和一个调用

特点

1.函数A作为参数出现,函数B接收函数A作为参数

2.要有闭包的特点

#定义一个装饰器
def decorator(func):
    a=100
    def wrapper(): #包装
        func()
        print('--->111')
        print('--->222',a)
    return wrapper
#使用装饰器
@decorator
#不改变原函数名字的情况下,对函数进行装饰
#开发中已经定义好了一个函数,但后来发现函数定义的有问题,想再丰富一下函数
#想再装饰一下
#函数ABC都要调用D,后来AB调用D发现不满足条件,要求D改动,而C对D要求不变
#不改变原名进行装饰
def house():
    print('我是毛坯房')
house()
'''
我是毛坯房
--->111
--->222 100
'''

decorator做了啥

def decorator(func):
    a=100
    print('wrapper外层打印测试')
    def wrapper(): #包装
        func()
        print('--->111')
        print('--->222',a)
    print('wrapper加载完成...')
    return wrapper
@decorator
def house(): #被装饰函数
    print('我是毛坯房')
print(house)
'''
wrapper外层打印测试
wrapper加载完成...
<function decorator.<locals>.wrapper at 0x000001B71917A3A0>
'''

1.house被装饰函数

2.将被装饰函数作为参数传给装饰器decorator

3.执行decorator函数(底层完成执行)

4.将返回值又赋值给house

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值