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 name
e age
:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
Linguagem de código: Python ( python )
Segundo, crie duas instâncias da Person
classe:
p1 = Person('John', 22)
p2 = Person('Jane', 22)
Linguagem de código: Python ( python )
Terceiro, mostre os hashes dos objetos p1
e p2
:
print(hash(p1))
print(hash(p2))
Linguagem de código: Python ( python )
Saída:
110373112736
110373572343
Linguagem 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 p1
objeto para a hash()
função:
hash(p1)
Linguagem de código: Python ( python )
Python chamará o __hash__
método do p1
objeto:
p1.__hash__()
Linguagem de código: Python ( python )
Por padrão, __hash__
usa a identidade do objeto e __eq__
retorna True
se 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 Person
classe 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.age
Linguagem de código: Python ( python )
Se você tentar usar o Person
objeto 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 Person
classe 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 Person
classe que oferece suporte à igualdade com base age
e pode ser hash.
Para funcionar Person
bem em estruturas de dados como dicionários, o hash da classe deve permanecer imutável. Para fazer isso, você pode tornar o age
atributo da Person
classe 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 ois
operador para comparações. - Se você implementar
__eq__
, o Python definirá__hash__
como,None
a menos que você implemente__hash__
.