>>> 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
和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
。
对于方法对象,“==”等于运算符由 Objects/methodobject.c 中的 meth_richcompare(...)
实现。
它包含了下面的逻辑,这解释了为什么“==”运算符返回 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
操作符更简单、更严格。它只比较PyCFunctionObj*
指针。它们将不同--来自不同的结构体并且是独立的对象,因此is
操作符将返回False
。is
和==
之间的行为差异是可以解释的。
is
提供了更强的保证,并且旨在快速和廉价(实质上是指针比较)。 ==
运算符检查对象,并在其内容匹配时返回True
。 在这个上下文中,函数指针是内容。