3 回答
TA贡献2019条经验 获得超9个赞
扩大伊格纳西奥的答案:
def counter():
count = 0
def c():
nonlocal count
count += 1
return count
return c
x = counter()
print([x(),x(),x()])
在Python 3中给出[1,2,3];counter()给独立计数器的调用。其他解决方案-尤其是使用itertools/ yield更惯用。
TA贡献1811条经验 获得超4个赞
您可以这样做,它或多或少会以相同的方式工作:
class counter(object):
def __init__(self, count=0):
self.count = count
def __call__(self):
self.count += 1
return self.count
或者,有点hack:
def counter():
count = [0]
def incr(n):
n[0] += 1
return n[0]
return lambda: incr(count)
我会选择第一个解决方案。
编辑:这就是我不阅读文本大博客所得到的。
无论如何,Python闭包相当有限的原因是“因为Guido感到喜欢”。Python是在90年代初期(即OO鼎盛时期)设计的。在人们想要的语言功能列表中,闭包率相当低。随着诸如一流函数,闭包之类的功能思想逐渐成为主流,诸如Python之类的语言不得不加以坚持,因此它们的使用可能有点尴尬,因为这不是该语言的设计目的。
<rant on="Python scoping">
另外,Python(2.x)在范围界定方面有很多奇怪的想法(在我看来),它们影响了闭包的合理实现等。它总是让我感到困扰:
new = [x for x in old]
x在我们使用的范围内给我们定义名称,因为它(在我看来)是概念上较小的范围。(尽管Python获得了一致性点,因为使用for循环执行相同的操作具有相同的行为。避免这种情况的唯一方法是使用map。)
无论如何, </rant>
TA贡献1842条经验 获得超21个赞
我会使用发电机:
>>> def counter():
count = 0
while True:
count += 1
yield(count)
>>> c = counter()
>>> c.next()
1
>>> c.next()
2
>>> c.next()
3
编辑:我相信您的问题的最终答案是PEP-3104:
在大多数支持嵌套作用域的语言中,代码可以引用或重新绑定(分配给)最近的封闭作用域中的任何名称。当前,Python代码可以在任何封闭范围内引用名称,但只能在两个范围内重新绑定名称:本地范围(通过简单分配)或模块全局范围(使用全局声明)。
在Python-Dev邮件列表和其他地方已经多次提出了此限制,并且导致了扩展讨论和许多关于消除此限制的方法的建议。该PEP总结了已提出的各种备选方案,以及每种方案的优缺点。
在2.1版之前,Python对范围的处理类似于标准C的处理:在文件中,只有两个级别的范围:全局和局部。在C语言中,这是自然的结果,因为函数定义不能嵌套。但是在Python中,尽管函数通常是在顶层定义的,但是函数定义可以在任何地方执行。这使Python看起来没有嵌套语义的嵌套作用域的语法外观,并产生了一些程序员惊讶的不一致之处-例如,在顶层使用的递归函数在移入另一个函数时将停止工作,因为递归函数的自己的名字在其范围内将不再可见。
添加回答
举报