>>> def QQ():
... a = 0
... def QQQ():
... global a
... a += 1
... QQQ()
...
>>> QQ()
NameError: global name 'a' is not defined
看起來global
在這種情況下不起作用。除了1元素列表技巧之外,我還能做什麼?如何重新綁定外部函數中的名稱?
>>> def QQ():
... a = 0
... def QQQ():
... global a
... a += 1
... QQQ()
...
>>> QQ()
NameError: global name 'a' is not defined
看起來global
在這種情況下不起作用。除了1元素列表技巧之外,我還能做什麼?如何重新綁定外部函數中的名稱?
如果你使用的是Python 3.x中,你可以使用nonlocal
:
>>> def QQ():
... a = 0
... def QQQ():
... nonlocal a
... a += 1
... QQQ()
... return a
...
>>> QQ()
1
如果你使用的是Python 2.x中,你不能做到這一點。這就是爲什麼添加nonlocal
的原因。所以,你必須使用某種可變的包裝,像1元列表伎倆。*
PEP 3104解釋了所有的血淋淋的細節(包括爲什麼Python沒有做「經典靜態嵌套作用域」在默認情況下,和要求你明確這一點)。
*或者升級到3.x,當然。每當你發現自己問如何綁定到非地址,委託給另一個生成器,獲取完全限定的類名,指定關鍵字參數,解壓變長迭代器,但分別捕獲最後一個值,或其他任何在3中微不足道的值。 x但在2.x中很痛苦,值得重新問自己是否該升級。
而不是創建一個任意列表,你可以使用內置的*args
和**kwargs
像
def f(**kwargs):
kwargs['start'] = kwargs.get('start', 0)
def g():
kwargs['start'] += 1
return kwargs['start']
return g
它本質上是相同的「黑客」,這只是不太難看海事組織。
我個人覺得這個也不那麼醜陋,但是「list hack」更爲人所知,並且在官方文檔(編程FAQ,PEP 3104,stdlib文檔中鏈接的示例代碼等)我通常以醜陋的方式去做。 (如果有幫助,告訴自己你在做什麼是一個詭計多端的解決方法,因此它更好看,更醜陋,更明顯......)無論如何,唯一的_clean_解決方案是(a)使用對象而不是閉包您需要重新綁定值,(b)在外部作用域中使用dict而不是單獨的變量,或者(c)升級到Python 3.x. – abarnert
這不是變異。 –
@ IgnacioVazquez-Abrams我該怎麼稱呼它?重新綁定? – chenaren
這完全正確。 –