为了账号安全,请及时绑定邮箱和手机立即绑定

读/写Python闭包

读/写Python闭包

GCT1015 2019-12-16 12:12:02
闭包是一种非常有用的语言功能。他们让我们做一些聪明的事情,这些事情本来需要很多代码,并且常常使我们能够编写更优雅,更清晰的代码。在Python 2.x中,闭包变量名不能反弹。也就是说,在另一个词法范围内定义的函数无法some_var = 'changed!'对其局部范围外的变量执行类似的操作。有人可以解释为什么吗?在某些情况下,我想创建一个在外部范围内重新绑定变量的闭包,但这是不可能的。我意识到,几乎在所有情况下(如果不是全部),这种行为都可以通过类来实现,但是它通常不那么简洁。为什么不能通过封闭方式进行?这是重新绑定闭包的示例:def counter():    count = 0    def c():        count += 1        return count    return c调用时,这是当前行为:>>> c()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "<stdin>", line 4, in cUnboundLocalError: local variable 'count' referenced before assignment我想要它做的是这样的:>>> c()1>>> c()2>>> c()3
查看完整描述

3 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

您可以这样做,它或多或少会以相同的方式工作:


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>



查看完整回答
反对 回复 2019-12-17
?
慕运维8079593

TA贡献1876条经验 获得超5个赞

我会使用发电机:


>>> 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看起来没有嵌套语义的嵌套作用域的语法外观,并产生了一些程序员惊讶的不一致之处-例如,在顶层使用的递归函数在移入另一个函数时将停止工作,因为递归函数的自己的名字在其范围内将不再可见。



查看完整回答
反对 回复 2019-12-17
  • 3 回答
  • 0 关注
  • 267 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信