Aby odpowiedzieć na to pytanie, musimy trochę zastanowić się nad tym, jak działa interpreter python. Może się różnić w innych implementacjach Pythona.
Najpierw zacznijmy od zdefiniowania funkcji os.remove
i os.unlink
. W Modules/posixmodule.c są zarejestrowani jako:
{"unlink", posix_unlink, METH_VARARGS, posix_unlink__doc__},
{"remove", posix_unlink, METH_VARARGS, posix_remove__doc__},
Uwaga, że wskaźniki funkcyjne zarówno punkt posix_unlink
w ich ml_meth
członka.
Dla obiektów metodowych operator równości ==
jest zaimplementowany przez meth_richcompare(...)
w Objects/methodobject.c.
Zawiera tę logikę, która wyjaśnia, dlaczego operator zwraca 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;
Dla wbudowanych funkcji m_self
jest NULL
tak eq
zaczyna się true
. Następnie porównujemy wskaźniki funkcji w ml_meth
(ten sam posix_unlink
, do którego odwołuje się powyższa struktura), a ponieważ pasują one do eq
pozostaje true
. Końcowy wynik jest taki, że pyton zwraca True
.
Operator is
jest prostszy i bardziej rygorystyczny. Operator is
porównuje tylko wskaźniki: PyCFunctionObj*
. Będą różne - pochodzą z różnych struktur i są odrębnymi obiektami, więc operator is
zwróci False
.
Uzasadnieniem jest to, że są one oddzielnymi obiektami funkcji (przypominają, że ich argumenty są różne), ale wskazują na tę samą implementację, więc różnica w zachowaniu między is
i ==
jest uzasadniona.
is
daje silniejszą gwarancję i ma być szybki i tani (w zasadzie porównanie wskaźnika). Operator ==
sprawdza obiekt i zwraca True
, gdy jego zawartość jest zgodna. W tym kontekście wskaźnik funkcji jest treścią.