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>
"""
|