2013-06-22 28 views
1
>>> def QQ(): 
...  a = 0 
...  def QQQ(): 
...   global a 
...   a += 1 
...  QQQ() 
... 
>>> QQ() 
NameError: global name 'a' is not defined 

看起來global在這種情況下不起作用。除了1元素列表技巧之外,我還能做什麼?如何重新綁定外部函數中的名稱?

+1

這不是變異。 –

+0

@ IgnacioVazquez-Abrams我該怎麼稱呼它?重新綁定? – chenaren

+0

這完全正確。 –

回答

3

如果你使用的是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中很痛苦,值得重新問自己是否該升級。

0

而不是創建一個任意列表,你可以使用內置的*args**kwargs

def f(**kwargs): 
    kwargs['start'] = kwargs.get('start', 0) 
    def g(): 
     kwargs['start'] += 1 
     return kwargs['start'] 
    return g 

它本質上是相同的「黑客」,這只是不太難看海事組織。

+0

我個人覺得這個也不那麼醜陋,但是「list hack」更爲人所知,並且在官方文檔(編程FAQ,PEP 3104,stdlib文檔中鏈接的示例代碼等)我通常以醜陋的方式去做。 (如果有幫助,告訴自己你在做什麼是一個詭計多端的解決方法,因此它更好看,更醜陋,更明顯......)無論如何,唯一的_clean_解決方案是(a)使用對象而不是閉包您需要重新綁定值,(b)在外部作用域中使用dict而不是單獨的變量,或者(c)升級到Python 3.x. – abarnert

相關問題