带有关闭的python计数器 [英] python counter with closure

查看:64
本文介绍了带有关闭的python计数器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用闭包属性在python中建立一个计数器。以下代码中的代码:

I'm trying to build a counter in python with the property of closure. The code in the following works:

def generate_counter():
    CNT = [0]
    def add_one():
        CNT[0] = CNT[0] + 1
        return CNT[0]
    return add_one

但是,当我将列表CNT更改为var时,它不起作用:

However when I change the list CNT to a var, it did not work:

def generate_counter1():
    x = 0
    def add_one():
        x = x + 1
        return x
    return add_one

当我打印实例的闭包属性时,我发现了 __ closure __ 第二种情况是没有:

when I print the closure property of an instance, I found the __closure__ of the second case is none:

>>> ct1 = generate_counter()
>>> ct2 = generate_counter1()
>>> print(ct1.__closure__[0])
<cell at 0xb723765c: list object at 0xb724370c>
>>> print(ct2.__closure__)
None

只是想知道为什么外部函数的索引必须是列表吗?

Just wondering why the index in outer function has to be a list?

感谢您的回答!找到可以清楚解释此问题的文档
https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable -has-a-value

Thanks for the answers! Found the docs which clearly explained this problem https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value

推荐答案

Python通过查看名称绑定行为来确定名称的范围;赋值就是这样一种行为(函数参数,导入,中的目标... 中的目标,而..作为目标是其他示例)。您在函数中绑定的名称被视为 local 。请参见 命名和绑定部分

Python determines the scope of a name by looking at name binding behaviour; assignment is one such behaviour (function parameters, importing, the target in for target ... or while .. as target are other examples). A name you bind to in a function is considered local. See the Naming and Binding section of the reference documentation.

因此,第二个示例中的名称 x local 变量,因为您直接分配给它:

So the name x in your second example is a local variable, because you assigned directly to it:

x = x + 1

实际上,因为您从未给 x 赋予局部值,所以您会得到当您尝试使用该功能时发生异常;尝试阅读时,本地名称为 unbound

In fact, because you never gave that x a local value, you'll get an exception when you try to use that function; the local name is unbound when you try to read it:

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

$之前引用了本地变量'x' b
$ b

在您的第一个示例中,没有这种绑定发生;您而是更改了 CNT 内容,该名称引用的内容未更改。

In your first example no such binding takes place; you are instead altering the contents of CNT, what that name references is not altered.

如果您使用的是Python 3,则可以使用 非本地语句

If you are using Python 3, you can override the decision to make a name local, by using a nonlocal statement:

def generate_counter2():
    x = 0
    def add_one():
        nonlocal x
        x = x + 1
        return x
    return add_one

通过将 x 设为非本地,Python会找到它

By making x non-local, Python finds it in the parent context and creates a closure for it again.

>>> 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中,您只能使用一些技巧,例如使用可变列表对象来规避绑定规则。另一个技巧是将计数器分配给嵌套函数的属性。再次,这避免了在当前范围内绑定名称:

nonlocal is new in Python 3; in Python 2 you are limited to tricks like using a mutable list object to evade the binding rule. Another trick would be to assign the counter to an attribute of the nested function; again, this avoids binding a name in the current scope:

def generate_counter3():
    def add_one():
        add_one.x += 1
        return add_one.x
    add_one.x = 0
    return add_one

这篇关于带有关闭的python计数器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆