Python 中的 is 和 id
(ob1 is ob2) 等價於(id(ob1) == id(ob2))
首先id函數可以獲得物件的記憶體位址,如果兩個物件的記憶體位址是一樣的,那麼這兩個物件肯定是一個對象。和is是等價的。 Python原始碼為證。
static PyObject * cmp_outcome(int op, register PyObject *v, register PyObject *w) { int res = 0; switch (op) { case PyCmp_IS: res = (v == w); break; case PyCmp_IS_NOT: res = (v != w); break;
但是請看下邊程式碼的這種情況怎麼會出現呢?
In [1]: def bar(self, x):
...: return self.x + y
...:
In [2]: class Foo(object):
In [2]: class Foo(object):
.. .: x = 9
...: def __init__(self ,x):
...: self.x = x
...: bar = bar
...:
In [3 ]: foo = Foo(5)
In [4]: foo.bar is Foo.bar
Out[4]: False
In [5]: id(foo.bar) == id(Foo.bar )
Out[5]: True
兩個物件用is判斷是False,用id判斷卻是True,這與我們已知的事實不符啊,這種現象該如何解釋呢?遇到這種情況最好的解決方法就是呼叫dis模組去看下兩個比較語句到底做了什麼。
In [7]: dis.dis("id(foo.bar) == id(Foo.bar)")
0 BUILD_MAP . 527
6
7 DELETE_GLOBAL 7 DELETE_GLOBAL 29281)
10 STORE_SLICE+1
11 SLICE+2 🜠 13 DELETE_SUBSCR
14 SLICE+2
18 PRINT_EXPR
19 JUMP_IF_FALSE_OR_POP 11887
_ 25 STORE_SLICE+1
In [8]: dis.dis("foo.bar is Foo.bar")
0 BUI_T
0 BUI
4 DELETE_GLOBAL 29281 (29281)
8 BUILD_MAP 8307
11 PRINT_EXPR SE 1887
15 DELETE_GLOBAL 29281 (29281) 真人的時候,兩個物件順序生成,放在堆疊裡相比較,由於地址不同肯定是False,但是id(foo.bar) == id(Foo.bar)的時候就不同了,首先生成foo.bar,然後計算foo.bar的位址,計算完之後foo.bar的位址之後,就沒有任何物件指向foo.bar了,所以foo.bar物件就會被釋放。然後產生Foo.bar對象,由於foo.bar和Foo.bar所佔用的記憶體大小是一樣的,所以又恰好重用了原先foo.bar的記憶體位址,所以id(foo.bar) == id(Foo. bar)的結果是True。 下面內容由郵件Leo Jay大牛提供,他解釋的更加通透。 用id(expression a) == id(expression b)來判斷兩個表達式的結果是不是同一個物件的想法是有問題的。 foo.bar 這種形式叫 attribute reference [1],它是表達式的一種。 foo是一個instance object,bar是一個方法,這個時候表達式foo.bar回傳的結果叫做method object [2]。依文件:When an instance attribute is referenced that isn't a data attribute, its class is searched. If the name denotes a valid class attribute 🜥(pointers to) the instance object and the function object just found together in an abstract object: this is the method object. foo.bar. method object,在id(foo.bar)這樣的表達式裡,method object只是一個暫時的中間變數而已,對暫時的中間變數做id是沒有意義的。 一個更明顯的例子是,print id(foo.bar) == id(foo.__init__) 輸出的結果也是True 㟎〜的文件[33]」 of an object. This is an integer (or long
integer) which is guaranteed to be unique and constant for this object
during its lifetime. Two objects with non-overlap lifetimes may
have the sameation ipping) ress of the object in memory. 只有你能保證物件不會被銷毀的前提下,你才能用id 來比較兩個物件。所以,如果你非要比的話,得這樣寫:fb = foo.bar Fb = Foo.bar print id(fb) == id(Fb) 綁定到名字上,再來比是不是同一個對象,你才能得到正確的結果。 is表達式 [4] 也是一樣的,你現在得到了正確的結果,完全是因為 CPython 現在的實作細節決定的。現在的is的實現,是左右兩邊的物件都計算出來,然後再比較這兩個物件的位址是否一樣。萬一哪天改成了,先算左邊,保存地址,把左邊釋放掉,再算右邊,再比較的話,你的is的結果可能就錯了。官方文件裡也提到了這個問題 [5]。我認為正確的方法也是像id那樣,先把左右兩邊都計算下來,並顯式綁定到各自的名字上,然後再用is判斷。
熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Python适合数据科学、Web开发和自动化任务,而C 适用于系统编程、游戏开发和嵌入式系统。Python以简洁和强大的生态系统著称,C 则以高性能和底层控制能力闻名。

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

Python在遊戲和GUI開發中表現出色。 1)遊戲開發使用Pygame,提供繪圖、音頻等功能,適合創建2D遊戲。 2)GUI開發可選擇Tkinter或PyQt,Tkinter簡單易用,PyQt功能豐富,適合專業開發。

Python更易學且易用,C 則更強大但複雜。 1.Python語法簡潔,適合初學者,動態類型和自動內存管理使其易用,但可能導致運行時錯誤。 2.C 提供低級控制和高級特性,適合高性能應用,但學習門檻高,需手動管理內存和類型安全。

要在有限的時間內最大化學習Python的效率,可以使用Python的datetime、time和schedule模塊。 1.datetime模塊用於記錄和規劃學習時間。 2.time模塊幫助設置學習和休息時間。 3.schedule模塊自動化安排每週學習任務。

Python在開發效率上優於C ,但C 在執行性能上更高。 1.Python的簡潔語法和豐富庫提高開發效率。 2.C 的編譯型特性和硬件控制提升執行性能。選擇時需根據項目需求權衡開發速度與執行效率。

Python在自動化、腳本編寫和任務管理中表現出色。 1)自動化:通過標準庫如os、shutil實現文件備份。 2)腳本編寫:使用psutil庫監控系統資源。 3)任務管理:利用schedule庫調度任務。 Python的易用性和豐富庫支持使其在這些領域中成為首選工具。

每天學習Python兩個小時是否足夠?這取決於你的目標和學習方法。 1)制定清晰的學習計劃,2)選擇合適的學習資源和方法,3)動手實踐和復習鞏固,可以在這段時間內逐步掌握Python的基本知識和高級功能。
