要回答这个问题,我们必须深入了解一下 python 解释器的工作原理。在其他 python 实现中可能会有所不同。
首先让我们从定义os.remove 和os.unlink 函数的地方开始。在Modules/posixmodule.c 他们注册为:
{"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__},
{"remove", posix_unlink, METH_VARARGS, posix_remove__doc__},
请注意,函数指针在其ml_meth 成员中都指向posix_unlink。
对于方法对象,== 相等运算符由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。在这种情况下,函数指针就是内容。