2011-07-04 99 views
14

奇怪:何時使用==以及何時使用?

>>> a = 123 
>>> b = 123 
>>> a is b 
True 
>>> a = 123. 
>>> b = 123. 
>>> a is b 
False 

似乎a is b被或多或少定義爲id(a) == id(b)。這樣很容易出錯:

basename, ext = os.path.splitext(fname) 
if ext is '.mp3': 
    # do something 
else: 
    # do something else 

一些fnames意外地在else塊中結束。修正很簡單,我們應該使用ext == '.mp3'來代替,但表面上的if ext is '.mp3'看起來像是一種很好的pythonic方法來編寫它,它比「正確」的方式更具可讀性。

由於字符串是不可變的,它的錯誤原因是什麼?什麼時候更好地檢查身份?什麼時候平等檢查更好?

+2

*相關:* [Python'=='vs'是'比較字符串','有時會失敗,爲什麼?](http://stackoverflow.com/questions/1504717/python-vs-is -comparing-strings-is-fails-sometimes-why) –

+0

可能的重複[何時\'== \'操作符不等同於\'is \'操作符? (Python)](http://stackoverflow.com/questions/3647692/when-is-the-operator-not-equivalent-to-the-is-operator-python) – user

+0

相關:http://stackoverflow.com/ a/2577589/674039 – wim

回答

5

據我所知,is檢查對象身份等價。由於沒有強制性的「字符串實習」,兩個恰好具有相同字符的字符串通常不是相同的字符串對象。

當您從一個字符串(或者,實際上是序列中的任何子序列)中提取一個子字符串時,您將最終得到兩個不同的對象,其中包含相同的值。

因此,當且僅當您比較對象標識時,請使用is。比較值時使用==

+3

其實,有_is_字符串實習。它不會發生動態創建的字符串。 – katrielalex

+0

@katrielalex有一個內建'intern()',它可以讓你明確*實習動態創建的字符串;它本身不會發生。 – Duncan

+1

@katriealex:我想我的意思是「自動和強制字符串實施」(我相信,有些語言可以做到這一點)。 – Vatine

20

它們從根本上不同。

  1. ==比較通過調用__eq__方法
  2. is返回true當且僅當兩個引用同一個對象

所以比較有發言權的Java:

  1. is==相同
  2. ==相同equals的對象
  3. 用於確定是否要使用
6

簡單的規則或==在Python

下面是一個簡單的規則(除非你想要去理論Python解釋器或者使用Python對象構建框架來做有趣的事情):

僅用於無比較。

if foo is None 

否則使用==。

if x == 3 

那麼你是安全的一面。上述評論已經解釋了這一點的基本原理。不要使用,如果你不是100%確定爲什麼要這樣做。

+1

他們Python的方式是可讀代碼,只要這就是你的意思(幾乎總是),就使用'=='。如果不是x:'如果不是x:'是Python的約定,那麼它將分別檢查'None True False'。當您檢查複雜的數據結構時,會使用'is'。 '如果l是mylist,則不聲明[l for mylist]'對(簡單)數據結構中的循環進行簡單檢查。 –

+0

什麼類型? 'type(「foo」)是str'可能是好的 –

0

將類似這樣的類定義爲用於API中常量的默認值也很有用。在這種情況下,使用比==運算符更爲正確。

class Sentinel(object): 
    """A constant object that does not change even when copied.""" 
    def __deepcopy__(self, memo): 
     # Always return the same object because this is essentially a constant. 
     return self 

    def __copy__(self): 
     # called via copy.copy(x) 
     return self 
相關問題