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().
@ 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.
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
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.
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 ().
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.
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
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.
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;
__hash__()
método .Respostas:
No glossário Python :
fonte
hash value
agora o que é valor de hash. você pode dar um exemplo__hash__()
. De maneira mais geral, consulte en.wikipedia.org/wiki/Hash_functionid(object)
é 16x o resultado deobject.__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).hash((1, [2, 3]))
vê-lo em ação. Publiquei uma solicitação para corrigir a entrada do glossário para hashable.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
fonte
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 exemplosLista de tipos imutáveis:
Lista de tipos mutáveis:
fonte
Ellipsis
também é um tipo imutável e pode ser usado como uma chave para adict
.hash(MyClass)
__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 daobject
(classe base universal).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:
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:
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.
fonte
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 ().
fonte
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.
fonte
id
, que é (aproximadamente) o endereço do objeto na memória.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á:
fonte
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.
fonte
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;
fonte