我希望这个小小的片段能够打印“为什么这不起作用?”有人可以帮助我理解为什么这不起作用,因为我的期望?我正在使用Python 2.6,如果这很重要的话。
class WhyDoesntThisWork(object):
def outer(self):
acc = ''
def inner(msg):
global acc
acc = acc + msg
inner("Why doesn't")
inner(" this work?")
print acc
WhyDoesntThisWork().outer()
global
语句,我会收到NameError: global name 'acc' is not defined
。global
声明,我会收到UnboundLocalError: local variable 'acc' referenced before assignment
。答案 0 :(得分:8)
我不知道为什么上面那么多评论都包含正确答案,没有人敢写出实际答案,所以我会在此做。
class ThisWorksNow(object):
def outer(self):
acc = []
def inner(msg):
acc.append(msg)
inner("Why doesn't")
inner(" this work?")
print "".join(acc)
ThisWorksNow().outer()
有什么区别?
为闭包中的对象指定名称在Python 2.x中不起作用,因为缺少Py3关键字nonlocal
,所以我们必须找到一种解决方法。
如果我们必须保持名称到对象绑定的常量,我们必须改变别的东西。在这种情况下,它是我们添加要添加的内容的对象。
print
行不是很优雅;也许打印其内容连接的对象可能更合适。
class StringBuilder(list): # class name stolen from Java
def __str__(self):
"""this makes the object printable in a way which represents the concatenated string"""
return "".join(self)
@property
def string(self):
"""this gives us a property which represents the concatenated string"""
return "".join(self)
# use whatever suits you better, one or both
有了这个,我们可以做到:
class ThisWorksNow(object):
def outer(self):
acc = StringBuilder()
def inner(msg):
acc.append(msg)
inner("Why doesn't")
inner(" this work?")
print acc
print acc.string # depending on what you take above
ThisWorksNow().outer()
编辑(追加):为什么global
不起作用?
我们也可以使用global
实现此目标,但有2个缺点。
acc
必须在我们使用它的两个地方全局化
class WhyDoesntThisWork(object):
def outer(self):
global acc
acc = ''
def inner(msg):
global acc
acc = acc + msg
此时我们将acc
次出现“提升”为“global
”级别。
acc
可以从外面修改。
如果我们在其他地方global acc
,或者我们在模块级别使用acc
,我们的流程可能会被篡改。应该避免这种情况。
答案 1 :(得分:0)
您可以创建一个如下所示的帮助器闭包类,以将变量显式标记为闭包。不确定这样的实用程序是否已经存在。
class closure:
def __init__(self, val = None):
self.val = val
def __call__(self, val = None):
if val:
self.val = val
return self.val
class WhyDoesntThisWork(object):
def outer(self):
acc = closure('')
def inner(msg):
acc(acc() + msg)
inner("Why doesn't")
inner(" this work?")
print acc
WhyDoesntThisWork().outer()