Python之函数进阶-闭包原理

闭包

  • 自由变量:未在本地作用域中定义的变量,例如定义在内层函数外的外层函数的作用域中的变量
  • 闭包:就是一个概念,出现在嵌套函数中,指的是内层函数引用到了外层函数的自由变量,就形成了闭包。很多语言都有这个概念,最熟悉的就是JavaScript

def inc():c = [0] # 自由变量def inner():c[0] += 1 # 此处+=的对象是列表中的地址引用return c[0]return inner# 定义一个函数,inner中c[0] += 1,是否可以修改inc中c变量呢?
foo = inc()print(1, foo())print(2, foo())# 执行结果是可以修改的,因为inner中修改的是列表中的引用地址。# 返回结果:1 1# 返回结果:2 2
c = 100print(foo())# 定义一个c=100的变量,然后在执行foo(),得到的结果是3,因为c变量是global全局的,print打印foo()函数,用的是函数内的变量,又执行一个所以是3.# 返回结果:3
def a():x = [1]return id(x)# 定义一个函数a,在函数体中定义一个变量,return 这个变量的id内存地址
a()# 返回结果:4375700544
a()# 每一次函数执行有关系吗?没有,是完全独立的# 返回结果:4371940480
def inc():a = (100,)c = [0]print(hex(id(c)))def inner():c[0] += 1print(a)return c[0]return innerfoo = inc()print(foo.__name__, type(foo.__name__))print(foo.__closure__)print(1, foo())print(2, foo())# inner中用到外层函数的自由变量被用到了,所以__closure__要记住,要不然就成垃圾了# 返回结果:0x104cf5fc0 # 将10进制转换成16进制# 返回结果:inner # foo的名字是inner,类型是str# 返回结果:(, ) # 执行closure得到的结果,在closure中记住了c的内存地址# 返回结果:(100,) # 第一次打印内容# 返回结果:1 1 # 第一次打印内容# 返回结果:(100,) # 第二次打印内容# 返回结果:2 2 # 第二次打印内容

图一:闭包原理