python闭包的详细解读

1、闭包的定义

  1. 闭包是嵌套在函数中的函数。

  2. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用。

2、理解闭包

  • 被引用的非全局变量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系。

  • 自由变量不会再内存中消失。

  • 外部函数返回了内部函数

通俗点说:

                闭包是一个函数,这个函数是嵌套在另外一个函数里边,且这个函数引用了外层函数的变量(非全局变量)

3、 闭包书写步骤

  • 定义外部函数

  • 定义外部函数,在内部函数中使用外部函数的变量

  • 外部函数返回内部函数的地址(内部函数名就饿内部函数的地址)

# 定义内部函数:
def outer(num):
    # 2.定义内部函数,在内部函数中使用外部函数的变量
    def inner(num1):
        print(num + num1)
 
    # 3.外部函数返回内部函数的地址
    return inner  # 函数名字就是函数地址
 
 
if __name__ == '__main__':
    # 创建闭包实例
    func = outer(100)  # 此时func相当于是inner
    # 调用闭包
    func(10)  # 此时调用inner函数,保存的num值为100
# 可以创建多个闭包实例,不同的闭包实例之间,不会相互影响

 4、闭包的使用

需求:

        根据配置信息使用闭包实现不同人的对话信息,例如对话:       

                张三:到北京了吗?

                李四:已经到了,放心吧。

 实现步骤说明:   

  • 定义外部函数接受不同的配置信息参数,参数是人名

  • 定义内部函数接受对话信息参数

  • 在内部函数里面把配置信息和对话信息进行拼接输出

def outer(name):
    # 定义内部函数,参数是 说话的信息
    print(f'{name}:到北京了吗?')
 
    def inner(name1):
        # 内部函数中,将name和info进行拼接输出
        print(f'{name1}:已经到了,放心吧。')
 
    # 外部函数返回内部函数的地址
    return inner
 
 
# 创建闭包实例
if __name__ == '__main__':
    func = outer('张三')
    func('李四')

 注意点:由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。

5、闭包修改外部函数变量(理解) 

函数内部想要修改全局变量,使用global关键字
在闭包函数内部,想要修改外部函数的局部变量,需要使用nonlocal关键字

def outer():
    num = 10
 
    def inner():
        # num = 100  # 不是修改外部变量的值,重新定义的局部变量
        nonlocal num  # 声明使用外部变量 num 不重新定义
        num = 100
 
    print(f'调用inner之前:{num}')
    inner()
    print(f'调用inner之后:{num}')
    return inner
 
 
func = outer()
func()

 6、闭包的作用

保存局部信息不被销毁,保证数据的安全性

 7、如何判断一个嵌套函数是不是闭包

  • 1,闭包只能存在嵌套函数中

  • 2, 内层函数对外层函数非全局变量的引用(使用),就会形成闭包。

案例1 :

def wrapper():
    a = 1
    def inner():
        print(a)
    return inner
ret = wrapper()

#例一是闭包

案例2:

# 例二:
a = 2
def wrapper():
    def inner():
        print(a)
    return inner
ret = wrapper()

#例二不是闭包

案例3:

# 例三:

def wrapper(a,b):
    def inner():
        print(a)
        print(b)
    return inner


a = 2
b = 3
ret = wrapper(a,b)

#也是闭包

8、如何用代码判断闭包?

查看这个函数有没有自由变量就行了

# 函数名.__code__.co_freevars 查看函数的自由变量
print(avg.__code__.co_freevars)  # ('series',)

# 函数名.__code__.co_varnames 查看函数的局部变量
print(avg.__code__.co_varnames)  # ('new_value', 'total')
# 函数名.__closure__ 获取具体的自由变量对象,也就是cell对象。
# (<cell at 0x0000020070CB7618: int object at 0x000000005CA08090>,)
# cell_contents 自由变量具体的值
print(avg.__closure__[0].cell_contents)  # []

 上面案例三最难判断是不是闭包,为了进一步确认,用代码判断闭包

# 例三:

def wrapper(a,b):
    def inner():
        print(a)
        print(b)
    return inner
a = 2
b = 3
ret = wrapper(a,b)

#如何用代码判断闭包?
print(ret.__code__.co_freevars)

('a', 'b')

Process finished with exit code 0

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值