的是'关键字在Python中是如何实现的?
... is
这个关键词可以用来判断字符串是否相等。
>>> s = 'str'
>>> s is 'str'
True
>>> s is 'st'
False
我试过 __is__()
和 __eq__()
,但都没有成功。
>>> class MyString:
... def __init__(self):
... self.s = 'string'
... def __is__(self, s):
... return self.s == s
...
>>>
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work
False
>>>
>>> class MyString:
... def __init__(self):
... self.s = 'string'
... def __eq__(self, s):
... return self.s == s
...
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work, but again failed
False
>>>
11 个回答
Python中的is
关键字用来检查两个对象是否是同一个对象。你不应该用它来判断字符串是否相等。虽然它看起来经常能用,但其实是因为Python在处理字符串时会做一种叫“驻留”的优化。简单来说,就是相同的字符串会被存储在一个内部的列表中,指向同一个对象。(这之所以可行,是因为Python中的字符串是不可变的。)
不过,像所有实现细节一样,你不应该依赖这个特性。如果你想判断两个字符串是否相等,应该使用==运算符。如果你真的想检查两个对象是否是同一个对象,那就用is
,但我很难想出有什么情况下你需要关心字符串对象的身份。可惜的是,你不能指望两个字符串在某种情况下会“故意”指向同一个对象,因为之前提到的驻留机制。
is
操作符的作用就像是比较两个对象的唯一标识符,也就是它们的 id(x)
值。举个例子:
>>> s1 = 'str'
>>> s2 = 'str'
>>> s1 is s2
True
>>> id(s1)
4564468760
>>> id(s2)
4564468760
>>> id(s1) == id(s2) # equivalent to `s1 is s2`
True
目前,id
是通过指针来进行比较的。所以你不能重载 is
操作符,也就是说不能改变它的默认行为。根据我所知道的,你也不能重载 id
。
所以,答案就是不可以。这在 Python 中比较少见,但就是这样。
用 is
来测试字符串只有在字符串被“内部化”的情况下才有效。除非你非常清楚自己在做什么,并且明确地进行了字符串的“内部化”,否则你绝对不应该在字符串上使用 is
。
is
是用来检查身份的,而不是相等性。这意味着 Python 只是比较对象在内存中的地址。is
基本上是在回答“我是否有两个名字指向同一个对象?” - 如果把它用来做其他事情就没有意义了。
举个例子,("a" * 100) is ("a" * 100)
的结果是假。通常情况下,Python 会把每个字符串写入不同的内存位置,只有在字符串是字面量时,才会进行“内部化”。