不能简单讲,这就要看一些底层的东西(堆栈结构等等,估计还和编译原理有关),我觉得重点在于延迟绑定怎么知道绑定的外层函数的局部变量
python的闭包是延迟绑定
什么是闭包?
- 出现函数嵌套, 即外层函数嵌套内层函数, 这就意味着c没有闭包,因为函数不能嵌套定义, 我猜的, 这块打个flag
- 内部函数引用外部函数的局部变量 一般我们知道,在栈中的局部变量在函数后退出后就销毁了, 那有什么办法可以不立即这么做?
- 外部函数返回值必须是内嵌函数
talk is cheap
#!/usr/bin/python
# -*- coding:utf-8 -*-
def multipliers():
name = "江湖狗哥我也"
i = 0
ret = list()
for _ in range(4):
lambda_func = lambda x: i * x + (print(name) is None) - 1 # noqa
ret.append(lambda_func)
print(lambda_func.__closure__)
print("the closure variable i: {}".format(hex(id(lambda_func.__closure__[0].cell_contents))))
i += 1
i = 100
return ret
if __name__ == '__main__':
for item in multipliers():
print("the lambda function output: {}".format(item(2)))
print("闭包中的cell对象组成的元组成: {}".format(item.__closure__))
print("取出闭包空间中的整数: {}".format(item.__closure__[0].cell_contents))
for number in list([0, 1, 2, 3, 100]):
print(hex(id(number)))
__
result
(<cell at 0x0000029926818FD0: int object at 0x0000029926026910>, <cell at 0x0000029926818FA0: str object at 0x0000029926576DC0>)
the closure variable i: 0x29926026910
(<cell at 0x0000029926818FD0: int object at 0x0000029926026930>, <cell at 0x0000029926818FA0: str object at 0x0000029926576DC0>)
the closure variable i: 0x29926026930
(<cell at 0x0000029926818FD0: int object at 0x0000029926026950>, <cell at 0x0000029926818FA0: str object at 0x0000029926576DC0>)
the closure variable i: 0x29926026950
(<cell at 0x0000029926818FD0: int object at 0x0000029926026970>, <cell at 0x0000029926818FA0: str object at 0x0000029926576DC0>)
the closure variable i: 0x29926026970
江湖狗哥我也
the lambda function output: 200
闭包中的cell对象组成的元组成: (<cell at 0x0000029926818FD0: int object at 0x00000299260555D0>, <cell at 0x0000029926818FA0: str object at 0x0000029926576DC0>)
闭包中的整数值: 100
江湖狗哥我也
the lambda function output: 200
闭包中的cell对象组成的元组成: (<cell at 0x0000029926818FD0: int object at 0x00000299260555D0>, <cell at 0x0000029926818FA0: str object at 0x0000029926576DC0>)
闭包中的整数值: 100
江湖狗哥我也
the lambda function output: 200
闭包中的cell对象组成的元组成: (<cell at 0x0000029926818FD0: int object at 0x00000299260555D0>, <cell at 0x0000029926818FA0: str object at 0x0000029926576DC0>)
闭包中的整数值: 100
江湖狗哥我也
the lambda function output: 200
闭包中的cell对象组成的元组成: (<cell at 0x0000029926818FD0: int object at 0x00000299260555D0>, <cell at 0x0000029926818FA0: str object at 0x0000029926576DC0>)
闭包中的整数值: 100
0x29926026910
0x29926026930
0x29926026950
0x29926026970
0x299260555d0
我特意加了一个字符串局部变量, name, 这里其实声明普通函数也可以,特意用了一些比较恶心的用法.
从下面代码我们知道什么
- 闭包空间就是一个元组,元素为cell对象, 每个cell对象又包含闭包内容和其它的内容
- 每个lambda函数引用外部函数的局部变量name和i这才形成了闭包
- 我在局部函数中把i值最后改成100,可以看到最后所有闭包空间中的int都是100了, 这个很合理,因为我改的是
局部变量,你引用了啊(这里我感觉既不是值传递也不是引用传递, 更不是共享传参, 就好像我盯着i这个标签一样,你怎么变,我最终值就怎么变) - 可以看到multipliers()调用之后就会出现延迟绑定, 即我所有匿名函数(这里是否是匿名函数没有关系), 最终闭包空间的所有值都是100
—————
延迟绑定只是一个表面现象,真正要理解我觉得还有一段路要走
看完龙书再回答一波.