在Python中测试引用相等性

47

假设我有一个Python类,其中定义了一个eq方法来比较属性是否相等:

class Foo(object):
    # init code...

    def __eq__(self, other):
        # usual eq code here....

我该如何比较两个Foo实例的引用相等性(即测试它们是否是同一个实例)?如果我这样做:

f1 = Foo()
f2 = Foo()
print f1 == f2
我得到True,尽管它们是不同的对象。

1
没关系,我想出来了,“is” 运算符:f1 = Foo() f2 = Foo() print f1 is f2返回 false。参考:http://www.tutorialspoint.com/python/python_basic_operators.htm - Adam Parkin
很棒,你自己找到了答案。即使你自己解决了问题,将解决方案作为常规答案而不是问题的评论仍然是合适的。 - SingleNegationElimination
我尝试过,但还没有足够的声望来这样做。 - Adam Parkin
@agf:好主意,但那听起来很像是对问题的回答。考虑将其作为答案添加进去。 - SingleNegationElimination
可能是重复的问题:如何在Python中检查两个变量是否引用同一个对象? - Ciro Santilli OurBigBook.com
显示剩余3条评论
3个回答

82

那是 is 运算符。

print f1 is f2

是的,我发帖后几乎马上就想通了。 :) 几分钟后将接受这个答案。谢谢。 - Adam Parkin
1
刚在终端运行了这段代码,能解释一下吗?
c = 5 d = 5 c == d True c is d True id(c) 4298161480 id(d) 4298161480
- Ryhan
1
@Ryan 请查看 https://dev59.com/NmEh5IYBdhLWcg3w6HEG - SingleNegationElimination

8

f1 is f2 用于检查两个引用是否指向同一个对象。在底层实现中,它会使用 id 内置函数比较 id(f1) == id(f2) 的结果,该函数返回一个整数,保证该整数在对象的生命周期内是唯一的(但仅限于对象的生命周期内)。

在 CPython 中,这个整数恰好是对象在内存中的地址,尽管文档中提到应该假装不知道这一点(因为其他实现可能有其他方法生成 id)。


6
使用 is 关键字。
print f1 is f2

一些有趣的事情(我认为这是实现相关的,但在CPython中是真实存在的)与关键字is相关,即None、True和False都是单例实例。因此,True is True将返回True。

在CPython中,字符串也是被联合(interned)的,所以'hello world' is 'hello world'将返回True(在正常代码中,您不应依赖此功能)。


2
只是注意CPython实现的另一个缺点:整数的id并不总是相同的... x=123123; ...some code...; x is 123123 有时会失败。这是因为整数“对象”是动态分配的,所以有时会创建重复项。据我所知,只有整数和字符串是以这种方式动态创建的,因此它们是唯一需要担心is会像这样表现的时间。 - Eli Collins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接