python代码:闭包closure的一个例子
#!/usr/bin/python # -*- coding: UTF-8 -*- """ @author: @file:closureExample.py @time:2022-04-03 12:26 """ # 书《Python核心编程(第二版).pdf》,作者:Wesley J. Chun # 例子:这个例子说明了如何能通过使用函数的__closure__属性来追踪闭包变量。 """ python闭包closure 在讨论闭包之前,先总结一下python的命名空间namespace,一般的语言都是通过namespace来识别名字标识,无论是变量,对象,函数等等。 python划分3个名字空间层次, local:局部,标识为当前函数内,当前类内,比如局部变量。 global:全局,标识当前模块,也就是当前文件,比如全局变量等。 最后一类 built-in,内建,这个是作用域比较大,跨模块(文件)都可以标识,比如我们自建的文件中,引用内建函数dir(), 这就是一个典型的例子,自建的文件中能够并没有声明dir(),但由于dir()是built_in内建函数,故在所有文件或模块都可以引用。 ---- 再来讨论闭包: closure概念:在一个内部函数中,对外部作用域的变量进行引用,那么内部函数就被认为是closure(闭包) 自由变量:定义在外部函数内,被内部函数引用或者使用的变量为自由变量 什么是自由变量?下面是关于自由变量在 Python 官方文档中的解释。 如果名称绑定在一个代码块中,则为该代码块的局部变量,除非声明为 nonlocal 或 global 。 如果名称绑定在模块层级,则为全局变量 (模块代码块的变量既为模块局部变量又为全局变量) 。 如果变量在一个代码块中被使用但不是在其中定义,则为自由变量。 结合namespace的概念,自由变量的位置:既不在函数local范围内,也不在全局global范围内,而是在两个函数的作用域之间。 ---- 所以简单地说,闭包从形式上说,就是函数内嵌一个函数。但是还需满足两个条件, 1.内层函数引用环境变量(自由变量) 2.外部函数返值为内部函数名(一个返回函数的高阶函数) ---- 再来说闭包有什么用? 闭包减少了参数的传递数量, 设计闭包是为了增加代码重复利用。 """ output = '<int %r id=%#0x val=%d>' w = x = y = z = 1 def f1(): x = y = z = 2 def f2(): y = z = 3 def f3(): z = 4 print(output % ('w', id(w), w)) print(output % ('x', id(x), x)) print(output % ('y', id(y), y)) print(output % ('z', id(z), z)) clo = f3.__closure__ if clo: print("f3 closure vars: ", [str(c) for c in clo]) else: print("no f3 closure vars") f3() clo = f2.__closure__ if clo: print("f2 closure vars: ", [str(c) for c in clo]) else: print("no f2 closure vars") f2() clo = f1.__closure__ if clo: print("f1 closure vars: ", [str(c) for c in clo]) else: print("no f1 closure vars") f1() """ Output: no f1 closure vars f2 closure vars: ['<cell at 0x0000027F1B58AFD0: int object at 0x0000027F0A266950>'] f3 closure vars: ['<cell at 0x0000027F1B58AFD0: int object at 0x0000027F0A266950>', '<cell at 0x0000027F1B58AF70: int object at 0x0000027F0A266970>'] <int 'w' id=0x27f0a266930 val=1> <int 'x' id=0x27f0a266950 val=2> <int 'y' id=0x27f0a266970 val=3> <int 'z' id=0x27f0a266990 val=4> """