What is the source code of __hash__() and __eq__() of object in Python?

不想你离开。 提交于 2019-12-06 11:17:35

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;
}

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!