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

Sri*_*nth 59 python built-in python-datamodel

... is可用于字符串中相等的关键字.

>>> s = 'str'
>>> s is 'str'
True
>>> s is 'st'
False
Run Code Online (Sandbox Code Playgroud)

我试过了两个__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
>>>
Run Code Online (Sandbox Code Playgroud)

Joc*_*zel 124

测试字符串is仅在字符串被实现时起作用.除非你真的知道自己在做什么,并明确实习的字符串,你应该永远不会使用is的字符串.

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

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

  • 我在过去观察到,如果运行时计算和输入值足够短,则可能会发生字符串实习.'a'*100不是'a'*100; 但是'a'*20是"a"*20.同时'a'.upper()不是'a'.upper().Jython,IronPython,PyPy和其他人可能会更积极地实习.简而言之,它依赖于实现.如上所述,在字符串上调用'intern()'函数将"强制"一个字符串与任何等效字符串和之前的intern()'字符串具有相同的对象标识.但是,我不知道测试字符串标识的有效用例.(除了可能的表现). (12认同)
  • `("a"*100)是("a"*100)`在2010年可能是假的,但今天它是真的. (4认同)

Phi*_*l H 20

is操作相当于比较id(x)值.id目前实现使用指针作为比较.所以你不能超载is自己,AFAIK也不能超载id.

所以,你做不到.在python中不寻常,但确实如此.


Jim*_*nis 16

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

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

  • @Lie Ryan:我倾向于同意.我只使用它作为None和我创建的特殊哨兵(通常作为对'base()'的调用).但是,我觉得很难确定'is'运算符没有其他有效用途; 只是没有我能想到的.(可能证明了我自己的无知). (2认同)

pyc*_*uft 8

is关键字进行比较的对象(或者说,如果比较两个引用是同一个对象).

我认为,这就是为什么没有机制来提供自己的实现.

它恰好在字符串上工作,因为Python"巧妙地"存储字符串,这样当你创建两个相同的字符串时,它们就存储在一个对象中.

>>> a = "string"
>>> b = "string"
>>> a is b
True
>>> c = "str"+"ing"
>>> a is c
True
Run Code Online (Sandbox Code Playgroud)

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

>>> a = {"a":1}
>>> b = a
>>> c = a.copy()
>>> a is b
True
>>> a is c
False
Run Code Online (Sandbox Code Playgroud)


tor*_*gen 5

如果你不怕搞乱字节码,可以COMPARE_OP8 ("is")参数拦截和修补,在被比较的对象上调用你的钩子函数.查看dis模块文档以了解启动情况.

而且不要忘了拦截__builtin__.id()太多,如果有人会做id(a) == id(b),而不是a is b.