2010-07-02 24 views
5

正如所有的Python程序員都知道,你應該使用的==代替is來比較兩個字符串是否相等。但是,實際上在Python 2.6.2中有哪些情況下(s is "")(s == "")會給出不同的結果?可以(s是「」)和(s ==「」)在Python 2.6.2中給出不同的結果嗎?

我最近碰到,在代碼審查中使用(s is "")代碼,並同時指出,這是不正確的,我想給這如何可能失敗的例子。但儘可能地嘗試,我不能構建兩個具有不同身份的空字符串。似乎Python的實現必須在許多常見操作中對空字符串進行特殊處理。例如:

>>> a = "" 
>>> b = "abc"[ 2:2 ] 
>>> c = ''.join([]) 
>>> d = re.match('()', 'abc').group(1) 
>>> e = a + b + c + d 
>>> a is b is c is d is e 
True 

然而,this question表明,有案件其中(s is "")(s == "")可以是不同的。任何人都可以給我一個例子嗎?

回答

11

正如其他人所說,不要依賴未定義的行爲。不過,既然你問一個具體的反例爲Python 2.6,那就是:

>>> s = u"\xff".encode('ascii', 'ignore') 
>>> s 
'' 
>>> id(s) 
10667744 
>>> id("") 
10666064 
>>> s == "" 
True 
>>> s is "" 
False 
>>> type(s) is type("") 
True 

唯一的一次了Python 2.6可以用一個空字符串這是不正常的空字符串結束是當它的字符串操作,並且事先不能確定該字符串的使用時間。所以當你編碼一個字符串時,錯誤處理程序可能會結束刪除字符並修復完成後的緩衝區大小。當然,這是一個疏忽,可以在Python 2.7中輕鬆更改。

12

的Python is測試對象的身份,而不是平等。下面是一個例子,其中使用is==給出了不同的結果:

>>> s=u"" 
>>> print s is "" 
False 
>>> print s=="" 
True 
+1

然而,這測試了兩種不同類型的字符串對象'str'和'unicode'。當s的類型相同時,或者如果您使用沒有顯式'unicode'對象的Python 3,問題仍然存在。 – poke 2010-07-02 11:53:55

+1

@poke,這個問題明確地集中在Python 2.6.2而不是Python 3上。 – zoli2k 2010-07-02 11:56:37

+0

沒錯,但它是一個重要的區別,這可能不是最好的方法。那個測試實際上是指那個代碼的意思?那'過去的事情相當於一個空的字符串',或者'過去的事物是str類型和空的'? Imo如果是後者,那麼明確的類型測試對於未來的維護者和用戶來說會更友好。 – pycruft 2010-07-02 11:57:27

3

它似乎對任何事情實際上是字符串工作的事,但它只是看起來像的字符串(如Unicode或str的子類或類似的東西)將會失敗。

>>> class mysub(str): 
    def __init__(self, *args, **kwargs): 
     super(mysub, self).__init__(*args, **kwargs) 

>>> 
>>> q = mysub("") 
>>> q is "" 
False 
>>> q == "" 
True 

編輯

對於代碼審查的目的&反饋我會建議,這是不好的做法,因爲它實現了一個意想不到的測試(即使我們忽略它是否會一直表現的不確定性當類型匹配時相同)。

if x is "" 

意味着x是正確的值和類型,但沒有類型的明確的測試這將提醒將來的維護或API用戶等

if x == "" 

意味着x只是正確的值

+0

當然,它們對於一個與str無關的類的對象來說是不同的,但它以等於字符串的方式執行\ _ \ _ eq \ _ \ _。 – jchl 2010-07-02 11:58:22

7

的你不應該在乎。與被定義爲單例的None不同,沒有規則說只有一個空字符串對象。所以s is ""的結果是依賴於實現的,並且使用is是否是NO-NO,無論您是否可以找到示例。

+0

我明白這一點。但爲了給一個初級程序員提供代碼審查反饋,最好說「不要這樣做,因爲它在這種情況下不起作用」,而不是說「不這樣做,因爲它是錯誤的」。當然,如果「因爲它是錯誤的」是唯一的原因,那麼這就是我不得不放棄的原因...... – jchl 2010-07-02 11:59:57

+1

那麼,你應該給你的初級程序員提供一個大局。最好知道'is'是測試'=='以外的東西,因此應該用於其正確的目的 - 偶然的事實,你可能會在幾種情況下逃避它是相當無關緊要的 - 嘗試學習反模式*做*工作的情況是一個浪費的努力和對未來錯誤的肯定的解決方案。 – 2010-07-02 12:07:00

+0

你應該說:「不要這樣做,因爲它是錯誤的,這是錯誤的,因爲不應該用'is'來檢查兩個值是否相等,只是爲了檢查它們是否是完全相同的實例。 – Blixt 2010-07-02 12:12:04

0

恐怕沒有,CPython的似乎優化""虛假情況遠於所有情況。但正如其他人所說,不要依賴這一點。

1

你不能找到一個例子,因爲有些東西是獨特的,而不是muteable - 所以Python留着那個只有一次,因此is作品。這些包括(), '',u'', True, False, None CPython甚至保留了一些常用的數字,即0, 0.0, 1, 1.0,

+2

從實驗上看,CPython(版本2.6.2)實際上是實現了從-5到256的所有整數。 – jchl 2010-07-02 12:06:42

+0

上面的列表中不應包含「0.0」和「1.0」:浮動不會被當前的CPython所限制。 – 2010-07-02 13:17:12

0

未定義的行爲是一個模糊的問題。 Python規範定義和遵守的實現必須符合,並且還有一些東西可供選擇。通過查看Python的源代碼,您可能會確信,實際的字符串對象不會發生這種行爲(與unicode與非unicode以及其他接近但不相關的示例不同)。很高興,你會在代碼中留下這樣的測試。

但是Python的實現並不能保證它總能正常工作。一些未來的實施可能會導致它改變,你會有一個痛苦的不兼容。

所以用這個經驗法則很簡單:不這樣做。使用操作符僅用於他們預期的和有據可查的使用。不要依賴可能在未來發生很大變化的實施工件。

相關問題