本帖最后由 ABC23 于 2018-4-24 11:06 编辑
一个简单的闭包问题。
对于新手来说很常见的疑问。
==================
def funX():
x = 5
def funY():
nonlocal x
x += 1
return x
return funY
def f():
a = funcX()
for i in range(3):
print(a())
print('='*12)
b = funcX()()
for i in range(3):
print(b)
================
➜ desktop python3
Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from dis import dis
>>> import pp
>>> dis(pp.f)
10 0 LOAD_GLOBAL 0 (funcX)
2 CALL_FUNCTION 0
4 STORE_FAST 0 (a)
11 6 SETUP_LOOP 26 (to 34)
8 LOAD_GLOBAL 1 (range)
10 LOAD_CONST 1 (3)
12 CALL_FUNCTION 1
14 GET_ITER
>> 16 FOR_ITER 14 (to 32)
18 STORE_FAST 1 (i)
12 20 LOAD_GLOBAL 2 (print)
22 LOAD_FAST 0 (a)
24 CALL_FUNCTION 0
26 CALL_FUNCTION 1
28 POP_TOP
30 JUMP_ABSOLUTE 16
>> 32 POP_BLOCK
13 >> 34 LOAD_GLOBAL 2 (print)
36 LOAD_CONST 4 ('============')
38 CALL_FUNCTION 1
40 POP_TOP
14 42 LOAD_GLOBAL 0 (funcX)
44 CALL_FUNCTION 0
46 CALL_FUNCTION 0
48 STORE_FAST 2 (b)
15 50 SETUP_LOOP 24 (to 76)
52 LOAD_GLOBAL 1 (range)
54 LOAD_CONST 1 (3)
56 CALL_FUNCTION 1
58 GET_ITER
>> 60 FOR_ITER 12 (to 74)
62 STORE_FAST 1 (i)
16 64 LOAD_GLOBAL 2 (print)
66 LOAD_FAST 2 (b)
68 CALL_FUNCTION 1
70 POP_TOP
72 JUMP_ABSOLUTE 60
>> 74 POP_BLOCK
>> 76 LOAD_CONST 0 (None)
78 RETURN_VALUE
>>>
===========================
你看看上面的字节码可能看懂?
解释:第一次测试,因为a = funcX(),返回内层函数,在Python中函数是一等公民,与类是平起平坐的,闭包保存环境信息(x=5),于是每次调用x +=1,5、6、7……好,在看第二个。
这次因为b = funcX()(),返回的是一个常量(变量名对应的常量对象6),这就不存在闭包环境了。于是:666(呵呵