[英]Confused about `is` operator with strings
is
運算符比較兩個對象的內存地址,如果它們相同則返回True
。 那么,為什么它不能與字符串一起可靠地工作? 代碼#1
>>> a = "poi"
>>> b = "poi"
>>> a is b
True
代碼#2
>>> ktr = "today is a fine day"
>>> ptr = "today is a fine day"
>>> ktr is ptr
False
我創建了兩個內容相同的字符串,但它們位於不同的內存地址上。 為什么的輸出is
運營商並不一致?
我相信這與字符串實習有關。 本質上,這個想法是只存儲每個不同字符串的一個副本,以提高某些操作的性能。
基本上, a is b
起作用的原因是(正如您可能已經猜到的)在這兩種情況下都有一個由 Python 引用的不可變字符串。 當字符串很大時(以及一些我不理解的其他因素,很可能),這不會完成,這就是為什么您的第二個示例返回 False。
編輯:事實上,奇怪的行為似乎是交互式環境的副作用。 如果您將相同的代碼放入 Python 腳本中,則a is b
和ktr is ptr
返回 True。
a="poi"
b="poi"
print a is b # Prints 'True'
ktr = "today is a fine day"
ptr = "today is a fine day"
print ktr is ptr # Prints 'True'
這是有道理的,因為 Python 很容易解析源文件並在其中查找重復的字符串文字。 如果您動態創建字符串,那么即使在腳本中它的行為也會有所不同。
a="p" + "oi"
b="po" + "i"
print a is b # Oddly enough, prints 'True'
ktr = "today is" + " a fine day"
ptr = "today is a f" + "ine day"
print ktr is ptr # Prints 'False'
至於為什么a is b
仍然導致 True ,也許分配的字符串小到足以保證在內部集合中快速搜索,而另一個不是?
is
是身份鑒定。 它適用於較小的一些字符串(由於緩存),但不適用於較大的其他字符串。 由於 str 不是 ptr。 [感謝埃里克森]
看到這個代碼:
>>> import dis
>>> def fun():
... str = 'today is a fine day'
... ptr = 'today is a fine day'
... return (str is ptr)
...
>>> dis.dis(fun)
2 0 LOAD_CONST 1 ('today is a fine day')
3 STORE_FAST 0 (str)
3 6 LOAD_CONST 1 ('today is a fine day')
9 STORE_FAST 1 (ptr)
4 12 LOAD_FAST 0 (str)
15 LOAD_FAST 1 (ptr)
18 COMPARE_OP 8 (is)
21 RETURN_VALUE
>>> id(str)
26652288
>>> id(ptr)
27604736
#hence this comparison returns false: ptr is str
注意str
和ptr
的 ID 是不同的。
但:
>>> x = "poi"
>>> y = "poi"
>>> id(x)
26650592
>>> id(y)
26650592
#hence this comparison returns true : x is y
x 和 y 的 ID 相同。 因此is
操作符適用於“ids”而不是“平等”
有關 Python 何時以及為何為相同字符串分配不同內存位置的討論,請參閱以下鏈接(也請閱讀問題)。
此外, sys.intern
上的 sys.intern 和 python2.x 上的intern
應該可以幫助您在相同的內存位置分配字符串,而不管字符串的大小。
is
不一樣的==
。
基本上, is
檢查兩個對象是否相同,而==
比較這些對象的值(字符串,就像 Python 中的所有內容一樣,都是對象)。
所以你應該使用is
當你真的知道你在看什么對象(即你已經創建了對象,或者正如問題注釋指出的那樣與None
進行比較),並且你想知道兩個變量是否正在引用內存中完全相同的對象。
但是,在您的示例中,您正在查看 python 在幕后處理的str
對象,因此如果不深入了解 python 的工作原理,您就不會真正知道會發生什么。 你會遇到同樣的問題int
s 或float
s。 其他答案很好地解釋了“幕后”的東西(字符串實習),但您在日常編程中通常不必擔心它。
請注意,這是 CPython 特定的優化。 如果你希望你的代碼是可移植的,你應該避免它。 例如,在 PyPy
>>>> a = "hi"
>>>> b = "hi"
>>>> a is b
False
還值得指出的是,對於小整數也會發生類似的事情
>>> a = 12
>>> b = 12
>>> a is b
True
您不應該再依賴它,因為其他實現可能不包括此優化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.