Каков исходный код __hash__() и __eq__() объекта в Python?

object является основой для всех новых классов стилей. Где я могу найти исходный код object? Я хотел бы посмотреть, как определены функции __hash__() и __eq__().

Обратитесь к этому ответу (Поиск исходного кода для встроенного Python функции?), я ищу определение объекта в cpython.

В https://hg.python нет определений __hash__() и __eq__(). org/cpython/file/tip/Objects/object.c.


person SparkAndShine    schedule 29.02.2016    source источник


Ответы (2)


Реализации по умолчанию для __hash__ и __eq__ унаследованы от базового типа object. Вы можете найти его определение типа в typeobject.c:

PyTypeObject PyBaseObject_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "object",                                   /* tp_name */
    …
    (hashfunc)_Py_HashPointer,                  /* tp_hash */
    …
    object_richcompare,                         /* tp_richcompare */
    …
};

Для хеш-функции (tp_hash) используется хэш-функция по умолчанию для ссылок, _Py_HashPointer. Он определен в 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;
}

Это в основном использует адрес указателя в качестве основы для хэша.

Когда вызывается __eq__, под капотом Python выполняет расширенное сравнение (tp_richcompare). Это включает в себя как проверку на равенство, так и проверку на неравноправие, а также сравнения, такие как больше или меньше. Реализация по умолчанию использует object_richcompare, что требует равенства ссылок :

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;
}
person poke    schedule 29.02.2016

Реализация object на самом деле находится в Objects/typeobject.c по какой-то причине. Глядя в этот файл, вы можете увидеть из определения PyBaseObject_Type:

PyTypeObject PyBaseObject_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "object",                                   /* tp_name */
    ...
    (hashfunc)_Py_HashPointer,                  /* tp_hash */
    ...
    object_richcompare,                         /* tp_richcompare */

что object.__eq__ реализовано в object_richcompare, а object.__hash__ реализовано в _Py_HashPointer из Python/pyhash.c.

В 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__ просто не существует, поэтому == в конечном итоге прибегает к сравнению указателей в default_3way_compare. _Py_HashPointer все еще существует, но находится в Objects/object.c.

person user2357112 supports Monica    schedule 29.02.2016