Reputation: 18017
object
is a base for all new style classes. Where can I find the source code of object
? I'd like to have a look how the function __hash__()
and __eq__()
are defined.
Refer to this answer (Finding the source code for built-in Python functions?), I search the object definition in cpython.
There is not __hash__()
and __eq__()
definiton in https://hg.python.org/cpython/file/tip/Objects/object.c.
Upvotes: 2
Views: 1066
Reputation: 280973
The object
implementation is actually in Objects/typeobject.c
, for some reason. Looking in that file, you can see from the PyBaseObject_Type
definition:
PyTypeObject PyBaseObject_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"object", /* tp_name */
...
(hashfunc)_Py_HashPointer, /* tp_hash */
...
object_richcompare, /* tp_richcompare */
that object.__eq__
is implemented in object_richcompare
, and object.__hash__
is implemented in _Py_HashPointer
from Python/pyhash.c
.
In Python 2.7:
PyTypeObject PyBaseObject_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"object", /* tp_name */
...
0, /* tp_compare */
...
(hashfunc)_Py_HashPointer, /* tp_hash */
...
0, /* tp_richcompare */
object.__eq__
simply doesn't exist, so ==
ultimately falls back on a pointer comparison in default_3way_compare
. _Py_HashPointer
still exists, but it's in Objects/object.c
Upvotes: 2
Reputation: 387755
The default implementations for __hash__
and __eq__
are inherited from the base object
type. You can find its type definition in typeobject.c
:
PyTypeObject PyBaseObject_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"object", /* tp_name */
…
(hashfunc)_Py_HashPointer, /* tp_hash */
…
object_richcompare, /* tp_richcompare */
…
};
For the hash function (tp_hash
), the default hash function for references is used, _Py_HashPointer
. It is defined in pyhash.c
:
Py_hash_t
_Py_HashPointer(void *p)
{
Py_hash_t x;
size_t y = (size_t)p;
/* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
excessive hash collisions for dicts and sets */
y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4));
x = (Py_hash_t)y;
if (x == -1)
x = -2;
return x;
}
This basically uses the pointer address as a base for the hash.
When __eq__
is called, what Python does under the hood is perform a rich comparison (tp_richcompare
). This includes both equality and non-equality check as well as comparisons like greater or lower than. The default implementation is using object_richcompare
which requires a reference equality:
static PyObject *
object_richcompare(PyObject *self, PyObject *other, int op)
{
PyObject *res;
switch (op) {
case Py_EQ:
/* Return NotImplemented instead of False, so if two
objects are compared, both get a chance at the
comparison. See issue #1393. */
res = (self == other) ? Py_True : Py_NotImplemented;
Py_INCREF(res);
break;
…
}
return res;
}
Upvotes: 4