上記のコメントの多くに正解が含まれている理由がわからないので、あえて実際の答えを書く人はいないので、ここで書きます。
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()
違いはなんですか?
クロージャー内にあるオブジェクトに名前を割り当てることは、Py3キーワードnonlocal
が欠落しているため、Python 2.xでは機能しません。そのため、回避策を見つける必要があります。
名前とオブジェクトの結合定数を一定に保つ必要がある場合は、別の変更を行う必要があります。この場合、追加するコンテンツを追加するのはオブジェクトです。
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
モジュールレベルで使用する場合、プロセスが改ざんされる可能性があります。これは避けるべきです。