2017-07-06 41 views
2

爲什麼調用f()()不一樣h=f()然後h()
當ID是爲f()h一樣嗎?返回的調用函數對象不顯示相同的結果? Python3.x

Python程序:

def f(): 
    c = [0] 
    def g(): 
    c[0] += 1 
    return c[0] 
    return g 

print (id(f()), id(f())) 
print (f()(), f()()) 

h = f() 
print (id(h)) 
print (h(), h()) 

輸出:

140383530386568 140383530386568 
1 1 
140383530386568 
1 2 

編輯:
和爲什麼的c值持續???

+2

因爲在第一種情況下,在創建新的功能,並調用它的飛行,兩次。 'c'作爲自由變量是指兩個不同的對象。在第二種情況下,您正在調用相同的功能。 ID恰好相同,因爲解釋器重用了相同的內存位置。 –

+0

@ juanpa.arrivillaga這似乎很好地回答了這個問題。我會建議張貼這個答案。 –

+0

在my.phone上,做不到正義 –

回答

3

要回答你的第二個問題,對於內部函數記憶的c值的原因是由於蟒蛇一個概念叫做功能關閉。即使當變量超出範圍

>>> def print_msg(msg): 
...  def foo(): 
...   print(msg) 
...  return foo 
... 
>>> f = print_msg('hello') 
>>> f() 
hello 

在封閉範圍,該值被記住或函數本身是從當前命名空間中刪除。

您可以通過訪問它的__closure__鉤子來查看函數的閉包內容:f._closure__[0].cell_contents


要回答你的第一個問題,當你調用f()()兩次,創建和動態返回函數。所以每次使用新版本c重新創建函數。第二次,當你把它分配給一個變量h,你到內部函數的引用,所以c值,因爲爲什麼我前面提到的保留。所以當你第二次調用同樣的函數時,c[0]的值會增加。

+0

剛剛意識到@黃打我一拳。 _Derp_。 –

+0

@ChristianDean以聽起來多餘爲代價。添加。 :P –

2

在Python中的一個概念closure

當你調用f,返回的對象包含__closure__屬性。 你可以通過調用h.__closure__檢查,並在你的情況,你可以通過調用h.__closure__[0].cell_contents得到 c

的閉合件是函數保留存在被定義的功能時,使得當函數被調用,並且限定範圍不再可用它們可在以後使用的自由變量的綁定。 - 流利的Python

+0

我只是做了''h___ closure__ [0] .cell_contents''',並且它實際上顯示了我們所期望的'''[3]'''。但是有沒有辦法看到它與名字'''''''相關? – Seoul

+0

@首爾是啊。如果每次調用內部函數時將函數修改爲'print(id(c))',您可以驗證。 –

+0

@首爾是的。你可以通過調用'h____ code __。co_freevars'來查看變量。 – Huang

相關問題