>>> 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
Why is that? Isn't os.unlink supposed to be an alias of 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
Why is that? Isn't os.unlink supposed to be an alias of os.remove?
To answer this question we have to dive a bit into the details of how the python interpreter works. It might be different in other python implementations.
First let's start where the
os.removeandos.unlinkfunctions are defined. In Modules/posixmodule.c they are registered as:Note that the function pointers both point to
posix_unlinkin theirml_methmember.For method objects, the
==equality operator is implemented bymeth_richcompare(...)in Objects/methodobject.c.It contains this logic, which explains why the
==operator returnsTrue.For built-in functions
m_selfisNULLsoeqstarts outtrue. We then compare the function pointers inml_meth(the sameposix_unlinkreferenced from the struct above) and since they matcheqremainstrue. The end result is that python returnsTrue.The
isoperator is simpler and stricter. Theisoperator only compares thePyCFunctionObj*pointers. They will be different -- they came from different structs and are distinct objects, so theisoperator will returnFalse.The rationale is likely that they are separate functions objects (recall their docstrings are different) but they point to the same implementation, so the difference in behavior between
isand==is justifiable.isbrings a stronger guarantee, and is meant to be fast and cheap (a pointer comparison, essentially). The==operator inspects the object and returnsTruewhen its content matches. In this context, the function pointer is the content.