Hash en Python

[Antecedentes del problema] Personalicé el tipo de objeto. Cuando usé set () para juzgar el peso, descubrí que la sobrecarga __eq__no funcionaba. Siempre pensé que era diferente.

[Causa del problema] Cuando se utiliza un objeto personalizado como un elemento de colección set (), debido a que el conjunto pertenece a la estructura de datos del algoritmo hash, el hash se juzga primero al juzgar el peso, y solo cuando el hash es el mismo Sigue siendo llamado __eq__a juzgar el peso. Lo mismo es cierto para otras estructuras de datos hash.

1. Cuando se __hash__llama al método mágico

Tenga en cuenta que este __hash__método mágico:

(1) Llamado por la función incorporada hash ()

(2) un conjunto de hash de tipo de hash propio miembro de operación: set(), frozenset([iterable]),dict(**kwarg)

2 Ejemplos de escenarios de aplicación

2.1 Solo use el __eq__juicio, no es necesario sobrecargar__hash__

Solo se llamará cuando los objetos se comparen utilizando el símbolo de paridad __eq__. En este momento, __hash__se puede obtener el resultado correcto sin sobrecargar :

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
class Student(object):
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def __hash__(self):
        print 'Call __hash__'
        
    def __eq__(self, other):
        print 'Call __eq__'
        if not isinstance(other, Student):
            return False
        return self._name == other._name and self._age == other._age

if __name__ == '__main__':
    s1 = Student('aa', 20)
    s2 = Student('aa', 20)
    s3 = Student('bb', 21)
    print s1 == s2
    print s1 == s3

2.2 Estrategia de comparación de la estructura hash

En la versión de la serie Python3.X, si solo está personalizado __eq__pero no definido __hash__, el Objeto no se puede usar como un elemento de estructura de datos hash (set, frozenset, dict). Porque en este momento automáticamente dejamos __hash__regresar Ninguno;

En la serie Python2.X, si solo se personaliza __eq__pero no se define __hash__, aún se puede usar como un elemento de estructura de datos hash (set, frozenset, dict). En este momento, causará un error en la comparación. Las razones son como sigue:

(1) La estructura hash primero llama al __hash__Objeto de comparación. La generación del valor hash predeterminado es diferente (relacionada con la dirección), por lo que siempre juzgará que los dos Objetos no son iguales, incluso si las asignaciones internas son las mismas;

(2) Cuando la estructura hash es __hash__igual, se seguirá llamando a la __eq__comparación.

class Student(object):
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def __hash__(self):
        print 'Call __hash__'
        return hash(self._name + str(self._age))  # 请注意这里一定要返回hash值,否则None报错

    def __eq__(self, other):
        print 'Call __eq__'
        if not isinstance(other, Student):
            return False
        return self._name == other._name and self._age == other._age

if __name__ == '__main__':
    s1 = Student('aa', 20)
    s2 = Student('aa', 20)
    s3 = Student('bb', 21)
    test_set = set()
    test_set.add(s1)
    print s2 in test_set    # True
    print s3 in test_set    # False

Supongo que te gusta

Origin blog.csdn.net/qdPython/article/details/112709966
Recomendado
Clasificación