https://foofish.net/python-closure.html

https://blog.csdn.net/liang19890820/article/details/73927601

del用法

del只是删除变量的标签

if __name__=='__main__':
    a=1
    b=a
    c=a
    del a
#    print(a)
'''
Traceback (most recent call last):
  File "<pyshell#12>", line 6, in <module>
    print(a)
NameError: name 'a' is not defined
'''
    print(b)
    #1

闭包

闭包满足的条件:

  • 存在一嵌套函数
  • 嵌套函数必须引用封闭(外界)函数中定义的值(也即自由变量)
  • 封闭函数必须返回嵌套函数

例子:

def outer(x):
    print("outer is used...")
    def inner():
        print("inner is used..")
        return x
    print("inner prepares return")
    return inner

重新写了一个例子,发现嵌套函数无法对传入外界函数的值123进行修改.

在内嵌函数中对x加1报错

Traceback (most recent call last):
  File "<pyshell#92>", line 1, in <module>
    f()
  File "<pyshell#88>", line 3, in inner
    x+=1
UnboundLocalError: local variable 'x' referenced before assignment

这个错误的意思是:内部的x在没有赋值(assignment)的情况下,被引用(referenced)了.

猜测:传入内嵌函数的数据是不可变对象,如果想保留原变量名赋值,
x+=1 or x=x+1,需要取出值,运算,再创建了一空间存放,即
新建了一个变量x指向新值,新变量和外部变量冲突?

ref提到

在一个作用域里面给一个变量赋值的时候,Python自动认为这个变量是这个作用域的本地变量,并屏蔽作用域外的同名的变量。很多时候可能在一个函数里添加一个赋值的语句会让你从前本来工作的代码得到一个UnboundLocalError。


传入list测试

def myouter():
    x=[1,2,3]
    print("outer的id:",id(x))
    def inner():
        x.pop()
        print("inner的id:",id(x))
        print("inner_outer_pop:",x)
        return x
    print("outer:",x)
    return inner
    '''
    outer的id: 2407175808520
    outer: [1, 2, 3]
    inner的id: 2407175808520
    inner_outer_pop: [1, 2]
    [1, 2]
    '''

继续查看资料

py3加入新关键字nonlocal

def outer():
    count=0
    def inner():
        nonlocal count
        count+=1
        return count
    return inner

即可解决之前的报错问题

闭包的好处

  • 装饰器
  • 取代硬编码中的常量
  • 避免使用全局值,并提供某种形式的数据隐藏。
  • 提供一致的函数签名
  • 实现面向对象

所有函数对象都有一个 __closure__ 属性,如果这个函数是一个闭包函数,那么会返回的是一个由 cell 对象组成的元组。cell 对象具有 cell_contents 属性,存储了闭包中的自由变量。

>>>sqr.__closure__
      
(<cell at 0x0000023076949B28: int object at 0x00007FFF390ED440>,)

>>>sqr.__closure__[0].cell_contents
      
2

标签: none

添加新评论