如何在Python中实现'is'关键字?

时间:2010-06-07 08:17:55

标签: python python-datamodel built-in

...可用于字符串中相等的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 个答案:

答案 0 :(得分:119)

使用is测试字符串仅在字符串被实现时才有效。除非你真的知道自己在做什么并明确interned,否则你应该永远在字符串上使用is

is测试身份,而非相等。这意味着Python只是简单地比较一个对象所在的内存地址。is基本上回答了问题“我对同一个对象有两个名字吗?” - 重载是没有意义的。

例如,("a" * 100) is ("a" * 100) False 。通常Python将每个字符串写入不同的内存位置,实际上主要用于字符串文字。

答案 1 :(得分:18)

is运算符相当于比较id(x)值。目前实现id以使用指针作为比较。所以你不能重载is本身,而AFAIK也不能重载id

所以,你不能。在python中不寻常,但它就是。

答案 2 :(得分:14)

Python is关键字测试对象标识。您不应该使用它来测试字符串相等性。它似乎经常工作,因为Python实现,如许多非常高级语言的实现,执行字符串的“实习”。也就是说,字符串文字和值在内部保存在散列列表中,而相同的字符串文字和值则呈现为对同一对象的引用。 (这是可能的,因为Python字符串是不可变的。)

但是,与任何实现细节一样,您不应该依赖于此。如果要测试相等性,请使用==运算符。如果你真的想测试对象标识然后使用is ---而且我很难想出一个你应该关心字符串对象标识的情况。不幸的是,由于前面提到的实习,你不能指望两个字符串是否是某种“故意”相同的对象引用。

答案 3 :(得分:8)

is关键字比较对象(或者,比较两个引用是否属于同一对象)。

我认为,为什么没有提供自己实现的机制。

它有时会在字符串上运行,因为Python“巧妙地”存储字符串,这样当你创建两个相同的字符串时,它们就存储在一个对象中。

>>> a = "string"
>>> b = "string"
>>> a is b
True
>>> c = "str"+"ing"
>>> a is c
True

您可以在一个简单的“复制”示例中看到参考与数据的比较:

>>> a = {"a":1}
>>> b = a
>>> c = a.copy()
>>> a is b
True
>>> a is c
False

答案 4 :(得分:5)

如果您不害怕弄乱字节码,可以使用COMPARE_OP参数拦截和修补8 ("is"),以便对要比较的对象调用钩子函数。查看dis模块文档以了解入门。

如果有人__builtin__.id()代替id(a) == id(b),也不要忘记截取a is b

答案 5 :(得分:2)

当字符串以' - '开头时,

无法将字符串变量与字符串值和两个字符串变量进行比较。我的Python版本是2.6.6

>>> s = '-hi'
>>> s is '-hi'
False 
>>> s = '-hi'
>>> k = '-hi'
>>> s is k 
False
>>> '-hi' is '-hi'
True

答案 6 :(得分:2)

'is'比较对象标识,而==比较值。

示例:

a=[1,2]
b=[1,2]
#a==b returns True
#a is b returns False

p=q=[1,2]
#p==q returns True
#p is q returns True

答案 7 :(得分:1)

您无法重载is运算符。您要重载的是==运算符。这可以通过在类中定义__eq__方法来完成。

答案 8 :(得分:1)

您正在使用身份比较。 == 可能就是你想要的。例外情况是,您要检查一个项目和另一个项目是否是完全相同的对象并且位于相同的内存位置。在您的示例中,项目不相同,因为一个项目的类型(my_string)与另一个项目(字符串)不同。此外,在python中没有someclass。__is__这样的东西(当然,除非你自己把它放在那里)。如果有的话,比较的对象对于简单地比较内存位置是不可靠的。

当我第一次遇到关键字时,它也让我很困惑。我原以为和==没什么不同。他们在许多对象上从解释器产生相同的输出。这种类型的假设实际上是 ...的用途。它是蟒蛇的等价物“嘿,不要误解这两个物体。它们是不同的。”,这本质上是什么[无论是谁让我理顺]说。思维方式大不相同,但有一点==另一点。

的 一些有用的例子和一些文本,以帮助解决有时令人困惑的差异 访问“Danny Yoo”撰写的a document from python.org's mail host

或者,如果离线,请使用我制作的unlisted pastebin身体。

如果他们在大约20个左右的蓝色卫星(蓝色卫星是一个真实的事件)中,都会失败,我会引用代码示例

###
>>> my_name = "danny"
>>> your_name = "ian"
>>> my_name == your_name
0                #or False
###

###
>>> my_name[1:3] == your_name[1:3]
1    #or True
###

###
>>> my_name[1:3] is your_name[1:3]
0
###

答案 9 :(得分:0)

在比较对象时,关键字很容易出现断言错误。例如,对象 a b 可能包含相同的值并共享相同的内存地址。因此,做一个

>>> a == b

将评估为

True

但是如果

>>> a is b

评估为

False

你应该检查

>>> type(a)

>>> type(b)

这些可能是不同的,也是失败的原因。

答案 10 :(得分:0)

由于字符串实习,这看起来很奇怪:

a = 'hello'
'hello' is a  #True

b= 'hel-lo'
'hel-lo' is b #False