Python__hash__

Resumo : neste tutorial, você aprenderá sobre a função hash() do Python e como substituir o __hash__método em uma classe personalizada.

Introdução à função hash Python

Vamos começar com um exemplo simples.

Primeiro, defina a Person classe com os atributos namee age:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = ageLinguagem de código:  Python  ( python )

Segundo, crie duas instâncias da Personclasse:

p1 = Person('John', 22)
p2 = Person('Jane', 22)Linguagem de código:  Python  ( python )

Terceiro, mostre os hashes dos objetos p1e p2:

print(hash(p1))
print(hash(p2))Linguagem de código:  Python  ( python )

Saída:

110373112736
110373572343Linguagem de código:  Python  ( python )

A hash()função aceita um objeto e retorna o valor hash como um número inteiro. Quando você passa um objeto para a hash()função, Python executará o __hash__método especial do objeto.

Isso significa que quando você passa o p1objeto para a hash()função:

hash(p1)Linguagem de código:  Python  ( python )

Python chamará o __hash__método do p1objeto:

p1.__hash__()Linguagem de código:  Python  ( python )

Por padrão, __hash__usa a identidade do objeto e __eq__retorna Truese dois objetos forem iguais. Para substituir esse comportamento padrão, você pode implementar os __eq__métodos e __hash__.

Se uma classe substituir o __eq__método, os objetos da classe se tornarão não laváveis. Isso significa que você não poderá usar os objetos em um tipo de mapeamento. Por exemplo, você não poderá usá-los como chaves em um dicionário ou como elementos em um conjunto .

A Personclasse a seguir implementa o __eq__método:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        return isinstance(other, Person) and self.age == other.ageLinguagem de código:  Python  ( python )

Se você tentar usar o Personobjeto em um conjunto, receberá um erro. Por exemplo:

members = {
    Person('John', 22),
    Person('Jane', 22)
}Linguagem de código:  Python  ( python )

Python emite o seguinte erro:

TypeError: unhashable type: 'Person'Linguagem de código:  Python  ( python )

Além disso, o objeto da Pessoa perde o hash porque se você implementar __eq__, o __hash__será definido como None. Por exemplo:

hash(Person('John', 22))Linguagem de código:  Python  ( python )

Erro:

TypeError: unhashable type: 'Person'Linguagem de código:  Python  ( python )

Para tornar a Personclasse hashável, você também precisa implementar o __hash__método:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        return isinstance(other, Person) and self.age == other.age

    def __hash__(self):
        return hash(self.age)Linguagem de código:  Python  ( python )

Agora, você tem a Personclasse que oferece suporte à igualdade com base agee pode ser hash.

Para funcionar Personbem em estruturas de dados como dicionários, o hash da classe deve permanecer imutável. Para fazer isso, você pode tornar o ageatributo da Personclasse uma propriedade somente leitura :

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age

    @property
    def age(self):
        return self._age

    def __eq__(self, other):
        return isinstance(other, Person) and self.age == other.age

    def __hash__(self):
        return hash(self.age)Linguagem de código:  Python  ( python )

Resumo

  • Por padrão, __hash__utiliza o id dos objetos e __eq__utiliza o isoperador para comparações.
  • Se você implementar __eq__, o Python definirá __hash__como, Nonea menos que você implemente __hash__.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *