web-dev-qa-db-fra.com

fonction de hachage en python

Je croyais que la fonction hash() fonctionnait de la même manière dans tous les interpréteurs Python. Mais cela diffère lorsque je l’exécute sur mon mobile avec python pour Android . Je reçois la même valeur de hachage pour le hachage des chaînes et des nombres, mais lorsque je hache des types de données intégrés, la valeur de hachage diffère.

PC Interprète Python (Python 2.7.3)

>>> hash(int)
31585118
>>> hash("hello sl4a")
1532079858
>>> hash(101)
101

Mobile Python Interpreter (Python 2.6.2)

>>> hash(int)
-2146549248
>>> hash("hello sl4a")
1532079858
>>> hash(101)
101

Quelqu'un peut-il me dire s'il s'agit d'un bug ou si j'ai mal compris quelque chose?.

26
bkmagnetron

pour les vieux python (au moins mon Python 2.7), il semble que

hash(<some type>) = id(<type>) / 16

et pour CPython id() est l’adresse en mémoire - http://docs.python.org/2/library/functions.html#id

>>> id(int) / hash(int)                                                     
16                                                                              
>>> id(int) % hash(int)                                                 
0                                                                               

donc je suppose que le port Android a une convention étrange pour les adresses de mémoire?

quoi qu'il en soit, compte tenu de ce qui précède, les hachages pour les types (et d'autres fonctions intégrées, je suppose) différeront d'une installation à l'autre, car les fonctions se trouvent à des adresses différentes.

en revanche, les hachages pour les valeurs (ce que je pense que vous entendez par "objets non internes") (avant que le contenu aléatoire ne soit ajouté) sont calculés à partir de leurs valeurs et donc vraisemblablement répétables.

PS mais il y a au moins une autre ride CPython:

>>> for i in range(-1000,1000):
...     if hash(i) != i: print(i)
...
-1

il y a une réponse quelque part ici expliquant celle-là ...

8
andrew cooke

hash() est randomisé par défaut chaque fois que vous démarrez une nouvelle instance de versions récentes (Python3.3 +) pour empêcher les attaques DOS par insertion de dictionnaire

Avant cela, hash() était de toute façon différent pour les versions 32 bits et 64 bits.

Si vous voulez quelque chose qui est hash à la même chose à chaque fois, utilisez un des hashs dans hashlib

>>> import hashlib
>>> hashlib.algorithms
('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
30
John La Rooy

Avec CPython, pour des raisons d'efficacité, hash() sur les objets internes renvoie la même valeur que id() , qui à son tour renvoie l'emplacement memory ("adresse") de l'objet.

D'un interprète basé sur CPython à un autre emplacement de mémoire d'un tel objet est sujet à modification. En fonction de votre système d'exploitation, cela peut changer d'une exécution à l'autre.

1
Sylvain Leroux

Le hachage de choses comme int repose sur id (), qui n'est pas garantie constante entre les exécutions ou entre les interprètes. C'est-à-dire que hash (int) produira toujours le même résultat lors de l'exécution d'un programme, mais il se peut que la comparaison ne soit pas égale entre les exécutions, sur la même plate-forme ou sur des plates-formes différentes.

BTW, bien que la randomisation de hachage soit disponible en Python, elle est désactivée par défaut. Puisque vos chiffres et vos chaînes sont égaux, ce n’est clairement pas le problème ici.

1
Sneftel

Depuis Python 3.3, l’algorithme de hachage par défaut a créé des valeurs de hachage qui sont salées avec une valeur aléatoire qui est différente même entre différents processus Python sur le même ordinateur.

Actuellement, seule la randomisation par hachage est implémentée pour les chaînes, car elle a été considérée comme le type de données le plus probable, capturé de l'extérieur, susceptible d'être attaqué.

Le même frozenset produit systématiquement la même valeur de hachage sur différentes machines ou même différents processus

Source: https://www.quora.com/Do-two-computers-produce-the-same-hash-for-identical-objects-in-Python

0
nabiltos