2015-05-27 65 views
-1

下面是簡單的Python代碼,Case 1和Case 2之間有什麼區別,爲什麼我在第一種情況下得到的結果爲False,在其他情況下爲True。在案例2中爲什麼id是相等的?dir(object)在內部調用object._dir __()嗎?如果是這樣,兩個調用的返回對象/結果應該是相同的。Python dir(object)vs object .__ dir __()

class Hello: 
    def __init__(self): 
     self.a1 = "a1" 


hello = Hello() 
print(hello) 

# Case 1 
var1 = dir(hello) 
var2 = hello.__dir__() 
print(id(var1), id(var2), id(var1) == id(var2)) 

# Case 2 
print(id(dir(hello)), id(hello.__dir__()), id(dir(hello)) == id(hello.__dir__())) 
print(dir(hello) == hello.__dir__()) 

輸出

<__main__.Hello object at 0x7f320828c320> 
139852862206472 139852862013960 False 
139852862014024 139852862014024 True 
False 
+0

如果你不認爲你的問題是重複的,請添加註釋以解釋原因。如果答案(無論是原始問題還是這個答案)都不涵蓋你想知道的所有內容,請添加評論。只需重複編輯您的問題,並希望我們會注意到這些更改只有在您的時機非常幸運時纔有效。 – abarnert

+0

@abarnert,我很新的stackoverflow。我會在下一次做,謝謝你讓我知道。 – ravi

+0

沒問題。我什麼都沒說,只是在我正要關閉頁面時偶然注意到其中一個編輯,並通過編輯我的答案來回答它,並且我不想給出錯誤的印象,即您可以依靠每天的這種時機。 – abarnert

回答

1

這只是你曾經得到True巧合。 (嗯,不是一個巧合,因爲CPython的實施使得它非常有可能...但它不是語言的要求。)

在案例1,您在var1var2有兩個不同的dict秒。他們同時活着,所以他們不能有相同的id

在情況2中,您再次有兩個不同的dict s--但是這一次,您沒有將它們存儲在任何地方;一旦你打電話給id,你就釋放它,這意味着它可以在你得到另一個*之前得到垃圾回收,**這意味着它最終可以重複使用相同的id***

注意,爲id文檔說:

這是保證是用於在其壽命期間該對象獨特和恆定的整數。具有非重疊壽命的兩個對象可能具有相同的id()值。

如果你真的想測試兩個表達式是否指向同一個對象,使用is,不比較他們的id秒。


你編輯的問題也問:

也做目錄(對象)調用object._dir __()在內部?

根據dir

如果對象有一個名爲__dir__()方法,這個方法將被調用,必須返回屬性的列表。

而且在__dir__數據模型節說:

dir()被稱爲對象上調用。必須返回一個序列。 dir()將返回的序列轉換爲列表並對其進行排序。

然後你說:

如果是兩個調用返回的對象應該是相同的。

那麼,這取決於你是什麼意思的「相同」。它應該返回等於的值(因爲沒有任何變化),但它不會是相同的值,這正是您要測試的值。 (如果不是顯而易見的,爲什麼dir爲您提供了一個新的列表中的每個時刻,它仍然應該清楚,它必須說:「dir()返回序列轉換到一個列表並對其排序,」其實這樣做......)


*由於CPython使用引用計數作爲其主垃圾回收機制,「可以收集」通常意味着「將立即收集」。對於大多數其他Python實現,這不是真的。

**如果您閱讀文檔時不清楚表達式部分的順序,那麼您可以嘗試dis.dis('id(dir(hello)) == id(hello.__dir__())')以按順序查看實際的字節碼。

***在CPython的,所述idPyObject結構表示對象的只是地址;如果一個PyObject被釋放,並且另一個相同類型被立即分配,它通常會得到相同的地址。

+0

對dir(object)和object._dir __()具有相同的id使我感到困惑,現在很明顯。謝謝。 另外如果dir(object)調用object .__ dir __(),爲什麼對__dir __()的調用沒有出現在反彙編代碼中? dis.dis('dir(hello)') – ravi