蟒蛇计数器与关闭
问题描述:
我想在python中建立一个计数器与闭包的属性。在以下工作中的代码:蟒蛇计数器与关闭
def generate_counter():
CNT = [0]
def add_one():
CNT[0] = CNT[0] + 1
return CNT[0]
return add_one
然而,当我改变列表CNT一个变种,它不工作:
def generate_counter1():
x = 0
def add_one():
x = x + 1
return x
return add_one
当我打印实例的封闭性,我找到了第二种情况是__closure__
没有:
>>> ct1 = generate_counter()
>>> ct2 = generate_counter1()
>>> print(ct1.__closure__[0])
<cell at 0xb723765c: list object at 0xb724370c>
>>> print(ct2.__closure__)
None
只是想知道为什么在外部函数的索引必须是一个列表?
感谢您的回答!找到明确解释此问题的文档 https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value
答
Python通过查看名称绑定行为来确定名称的范围;赋值就是这样一种行为(函数参数,导入,目标在for target ...
或while .. as target
是其他例子)。在函数中绑定的名称被认为是本地。请参阅参考文档的Naming and Binding section。
所以在你的第二个例子名称x
是本地变量,因为你直接分配给它:
x = x + 1
事实上,因为你从来没有给该x
局部值,你会得到当您尝试使用该功能时出现异常;本地名称是绑定当您尝试阅读:
>>> generate_counter1()()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in add_one
UnboundLocalError: local variable 'x' referenced before assignment
在你的第一个例子中,没有这样的结合发生;您改为的内容的CNT
,该名称引用的内容未被更改。
如果您正在使用Python 3,你可以重写决定做一个名字的地方,通过使用nonlocal
statement:
def generate_counter2():
x = 0
def add_one():
nonlocal x
x = x + 1
return x
return add_one
通过使x
非本地,Python的发现它的父上下文,并创建再次关闭它。
>>> def generate_counter2():
... x = 0
... def add_one():
... nonlocal x
... x = x + 1
... return x
... return add_one
...
>>> generate_counter2().__closure__
(<cell at 0x1078c62e8: int object at 0x1072c8070>,)
nonlocal
是Python 3中的新增功能;在Python 2中,你仅限于使用可变列表对象来逃避绑定规则的技巧。另一个技巧是将计数器分配给嵌套函数的属性;再次,这避免了在当前范围绑定的名称:
def generate_counter3():
def add_one():
add_one.x += 1
return add_one.x
add_one.x = 0
return add_one
看起来像这是一个副本http://*.com/questions/4851463/python-closure-write-to-variable-in-parent-scope – ChatterOne