2

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.

Community
  • 1
  • 1
SparkAndShine
  • 17,001
  • 22
  • 90
  • 134
  • 1
    Not sure about equality but for hashing you might want to look [at this file](https://github.com/python/cpython/blob/master/Python/pyhash.c) – Two-Bit Alchemist Feb 29 '16 at 21:00
  • 1
    @Waylan: Despite what it might look like, those functions aren't actually the `object.__eq__` or `object.__hash__` implementations. – user2357112 Feb 29 '16 at 21:04

2 Answers2

4

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;
}
poke
  • 369,085
  • 72
  • 557
  • 602
2

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

user2357112
  • 260,549
  • 28
  • 431
  • 505