O que significa "lavável" em Python?

193

Tentei pesquisar na Internet, mas não consegui encontrar o significado de hashable.

Quando eles dizem que os objetos são hashableou hashable objectso que isso significa?

user1755071
fonte
1
Consulte a documentação sobre hashable e o __hash__()método .
precisa saber é o seguinte
5
que procura por objetos hasable ou algo, mas nenhum dos links explica o que Hashable realmente significa
user1755071
possível duplicação de Hashable, imutável
Todos os trabalhadores são essenciais

Respostas:

181

No glossário Python :

Um objeto é lavável se tiver um valor de hash que nunca muda durante sua vida útil (precisa de um __hash__()método) e pode ser comparado a outros objetos (precisa de um __eq__()ou __cmp__()método). Objetos hashable que comparam iguais devem ter o mesmo valor de hash.

A capacidade de Hashability torna um objeto utilizável como chave de dicionário e membro do conjunto, porque essas estruturas de dados usam o valor de hash internamente.

Todos os objetos internos imutáveis ​​do Python são laváveis, enquanto não há contêineres mutáveis ​​(como listas ou dicionários). Objetos que são instâncias de classes definidas pelo usuário são hashable por padrão; todos eles comparam desiguais, e seu valor de hash é o deles id().

NPE
fonte
2
se tiver hash valueagora o que é valor de hash. você pode dar um exemplo
user1755071
2
@ user55711: Aqui, o valor do hash é o resultado da chamada __hash__(). De maneira mais geral, consulte en.wikipedia.org/wiki/Hash_function
NPE
16
@ TorstenBronger: porque dois objetos desiguais podem hash com o mesmo valor. Em outras palavras, o hash é com perdas.
NPE
1
No python-2.7.12, o resultado de id(object)é 16x o resultado de object.__hash__(). Portanto, o trecho do glossário está incorreto para esta versão - o valor do hash não é id(), mas é derivado dele (como de fato observado nos documentos atualizados para o python 2.7.12).
Davida
2
Sei que este é um post antigo, mas vale a pena mencionar que a entrada do glossário copiada aqui não está totalmente correta. Você pode colocar um objeto mutável (como uma lista) dentro de uma tupla. A tupla ainda é imutável, mas você pode alterar a lista dentro dela, para que não seja lavável. Tente hash((1, [2, 3]))vê-lo em ação. Publiquei uma solicitação para corrigir a entrada do glossário para hashable.
John Riehl
102

Todas as respostas aqui têm uma boa explicação prática de objetos hash em python, mas acredito que é preciso entender primeiro o termo Hashing.

Hashing é um conceito em ciência da computação usado para criar estruturas de dados de acesso pseudo-aleatório de alto desempenho, nas quais uma grande quantidade de dados deve ser armazenada e acessada rapidamente.

Por exemplo, se você possui 10.000 números de telefone e deseja armazená-los em uma matriz (que é uma estrutura de dados seqüencial que armazena dados em locais de memória contíguos e fornece acesso aleatório), mas pode não ter a quantidade necessária de contíguos locais de memória.

Portanto, você pode usar uma matriz de tamanho 100 e usar uma função hash para mapear um conjunto de valores para os mesmos índices, e esses valores podem ser armazenados em uma lista vinculada. Isso fornece um desempenho semelhante a uma matriz.

Agora, uma função de hash pode ser tão simples quanto dividir o número pelo tamanho da matriz e considerar o restante como o índice.

Para mais detalhes, consulte https://en.wikipedia.org/wiki/Hash_function

Aqui está outra boa referência: http://interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html

ojas mohril
fonte
1
Essa é uma perspectiva interessante sobre hash. Eu não pensei nisso dessa maneira.
yuvgin 01/01
As tabelas de hash @yuvgin são frequentemente usadas para implementar matrizes esparsas (ou seja, o exemplo dado aqui).
Eli Korvigo 01/03/19
@EliKorvigo Eu gosto de pensar em matrizes regulares como simplesmente versões altamente otimizadas de uma tabela de hash.
Mark Ransom
1
você pode produzir um código simples em relação ao cenário da matriz de números de telefone para esclarecer o conceito de hash?
Istiaque Ahmed 18/01
18

Qualquer coisa que não seja mutável (meios mutáveis, com probabilidade de mudar) pode ser hash. Além da função hash a ser procurada, se houver uma classe, por exemplo. dir(tuple)e procurando o __hash__método, aqui estão alguns exemplos

#x = hash(set([1,2])) #set unhashable
x = hash(frozenset([1,2])) #hashable
#x = hash(([1,2], [2,3])) #tuple of mutable objects, unhashable
x = hash((1,2,3)) #tuple of immutable objects, hashable
#x = hash()
#x = hash({1,2}) #list of mutable objects, unhashable
#x = hash([1,2,3]) #list of immutable objects, unhashable

Lista de tipos imutáveis:

int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes

Lista de tipos mutáveis:

list, dict, set, bytearray, user-defined classes
user1767754
fonte
Recentemente, descobri que o Ellipsistambém é um tipo imutável e pode ser usado como uma chave para a dict.
Gábor Fekete
Mesmo classes definidas pelo usuário podem ser usadas, mas apenas seus nomes, não instâncias. Por exemplo:hash(MyClass)
Gábor Fekete
1
As instâncias @ GáborFekete de classes definidas pelo usuário são hashable se suas classes implementarem __hash__e __eq__. Além disso, todas as classes definidas pelo usuário implementam esses métodos (e, portanto, são hashable), porque elas herdam os métodos da object(classe base universal).
Eli Korvigo 01/03/19
6

No meu entendimento, de acordo com o glossário Python, quando você cria uma instância de objetos que são hasháveis, um valor imutável também é calculado de acordo com os membros ou valores da instância. Por exemplo, esse valor pode ser usado como uma chave em um ditado como abaixo:

>>> tuple_a = (1,2,3)
>>> tuple_a.__hash__()
2528502973977326415
>>> tuple_b = (2,3,4)
>>> tuple_b.__hash__()
3789705017596477050
>>> tuple_c = (1,2,3)
>>> tuple_c.__hash__()
2528502973977326415
>>> id(a) == id(c)  # a and c same object?
False
>>> a.__hash__() == c.__hash__()  # a and c same value?
True
>>> dict_a = {}
>>> dict_a[tuple_a] = 'hiahia'
>>> dict_a[tuple_c]
'hiahia'

podemos descobrir que o valor do hash de tuple_a e tuple_c são os mesmos, pois eles têm os mesmos membros. Quando usamos tuple_a como a chave em dict_a, podemos descobrir que o valor para dict_a [tuple_c] é o mesmo, o que significa que, quando usados ​​como chave em um dict, eles retornam o mesmo valor porque os valores de hash são o mesmo. Para os objetos que não são hasháveis, o hash do método é definido como Nenhum:

>>> type(dict.__hash__) 
<class 'NoneType'>

Eu acho que esse valor de hash é calculado na inicialização da instância, não de forma dinâmica, é por isso que apenas objetos imutáveis ​​são hashable. Espero que isto ajude.

Jay.Zhao
fonte
4

Deixe-me dar um exemplo de trabalho para entender os objetos hash em python. Estou usando 2 tuplas neste exemplo. Cada valor de uma tupla tem um valor de hash exclusivo que nunca muda durante a vida útil. Portanto, com base nesse valor, é feita a comparação entre duas tuplas. Podemos obter o valor de hash de um elemento de tupla usando o Id ().

Comparação entre 2 tuplasEquivalência entre 2 tuplas

bks4line
fonte
26
isso seria mais útil como texto em vez de uma imagem
Baxx
6
é uma resposta errada. id () mostra o endereço referenciado na memória, não é um valor de hash. Para obter o hash, use a função __hash __ (). por exemplo: t1 .__ hash __ ()
Vlad
@ascentman Não hesite em editar uma resposta que você acredita estar errada. Sua edição será revisada por pares e, se aceita, você receberá uma pequena recompensa por pontuação.
XavierStuvw
4

Em python, isso significa que o objeto pode ser membro de conjuntos para retornar um índice. Ou seja, eles têm uma identidade / ID único.

por exemplo, no python 3.3:

as listas da estrutura de dados não são laváveis, mas as Tuplas da estrutura de dados são laváveis.

naghceuz
fonte
O hash não é o mesmo que id, que é (aproximadamente) o endereço do objeto na memória.
Pool #
3

Hashable = capaz de ser hash.

Ok, o que é hash? Uma função de hash é uma função que pega um objeto, digamos uma string como "Python", e retorna um código de tamanho fixo. Para simplificar, suponha que o valor de retorno seja um número inteiro.

Quando executo hash ('Python') no Python 3, recebo 5952713340227947791 como resultado. Versões diferentes do Python são livres para alterar a função hash subjacente; portanto, você provavelmente obterá um valor diferente. O importante é que agora não importa quantas vezes eu execute o hash ('Python'), sempre obterei o mesmo resultado com a mesma versão do Python.

Mas o hash ('Java') retorna 1753925553814008565. Portanto, se o objeto que estou usando o hash for alterado, o resultado também será alterado. Por outro lado, se o objeto que estou trocando de hash não mudar, o resultado permanecerá o mesmo.

Por que isso importa?

Bem, dicionários Python, por exemplo, exigem que as chaves sejam imutáveis. Ou seja, as chaves devem ser objetos que não mudam. Strings são imutáveis ​​em Python, assim como os outros tipos básicos (int, float, bool). Tuplas e frozensets também são imutáveis. As listas, por outro lado, não são imutáveis ​​(ou seja, são mutáveis) porque você pode alterá-las. Da mesma forma, os ditados são mutáveis.

Então, quando dizemos que algo é lavável, queremos dizer que é imutável. Se eu tentar passar um tipo mutável para a função hash (), ela falhará:

>>> hash('Python')
1687380313081734297
>>> hash('Java')
1753925553814008565
>>>
>>> hash([1, 2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash({1, 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> hash({1 : 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
>>> hash(frozenset({1, 2}))
-1834016341293975159
>>> hash((1, 2))
3713081631934410656
Sidrah
fonte
1
Observe que o python aleatoriamente semeia o algoritmo de hash no início de cada processo. Portanto, você obterá diferentes valores de hash se executar o hash ('Python') duas vezes em processos diferentes.
D Hudson
2

No Python, qualquer objeto imutável (como um número inteiro, booleano, string, tupla) é lavável, o que significa que seu valor não muda durante sua vida útil. Isso permite que o Python crie um valor de hash exclusivo para identificá-lo, que pode ser usado pelos dicionários para rastrear chaves e conjuntos exclusivos para rastrear valores exclusivos.

É por isso que o Python exige que usemos tipos de dados imutáveis ​​para as chaves em um dicionário.

Akku2403
fonte
-1

Para criar uma tabela de hash do zero, todos os valores devem ser definidos como "Nenhum" e modificados assim que surgir um requisito. Objetos hashable referem-se aos tipos de dados modificáveis ​​(dicionário, listas etc.). Os conjuntos, por outro lado, não podem ser reinicializados depois de atribuídos, portanto, os conjuntos não são hasháveis. Visto que, a variante do conjunto () - frozenset () - é lavável;

JAY
fonte