>>> import sys
>>> sys.version
'2.7.3 (default, Mar 13 2014, 11:03:55) \n[GCC 4.7.2]'
>>> import os
>>> os.remove is os.unlink
False
>>> os.remove == os.unlink
True
这是为什么?os.unlink 不应该是 os.remove 的别名吗?
>>> import sys
>>> sys.version
'2.7.3 (default, Mar 13 2014, 11:03:55) \n[GCC 4.7.2]'
>>> import os
>>> os.remove is os.unlink
False
>>> os.remove == os.unlink
True
这是为什么?os.unlink 不应该是 os.remove 的别名吗?
要回答这个问题,我们必须深入了解 Python 解释器的工作原理。在其他 python 实现中可能会有所不同。
首先让我们从定义os.remove
andos.unlink
函数的地方开始。在Modules/posixmodule.c中,它们被注册为:
{"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__},
{"remove", posix_unlink, METH_VARARGS, posix_remove__doc__},
请注意,函数指针都指向posix_unlink
它们的ml_meth
成员。
对于方法对象,==
相等运算符meth_richcompare(...)
在Objects/methodobject.c中实现。
它包含这个逻辑,它解释了为什么==
操作符返回True
。
a = (PyCFunctionObject *)self;
b = (PyCFunctionObject *)other;
eq = a->m_self == b->m_self;
if (eq)
eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
对于内置函数m_self
就是NULL
这么eq
开始的true
。然后我们比较函数指针ml_meth
(与posix_unlink
上面的结构引用的相同),因为它们匹配eq
仍然true
。最终结果是 python 返回True
.
操作员更简单,is
更严格。is
运算符仅比较指针PyCFunctionObj*
。它们会有所不同——它们来自不同的结构并且是不同的对象,因此is
运算符将返回False
。
理由很可能是它们是独立的函数对象(回想一下它们的文档字符串不同),但它们指向相同的实现,因此is
和之间的行为差异==
是合理的。
is
带来了更强的保证,并且意味着快速和便宜(本质上是指针比较)。==
操作员检查对象并在其True
内容匹配时返回。在这种情况下,函数指针就是内容。