Zusammenfassung: Es ist kein Zufall; _PyHASH_INF
ist in der Standard-CPython-Implementierung von Python als 314159 fest codiert und wurde von Tim Peters im Jahr 2000 als beliebiger Wert (offensichtlich aus den Ziffern von π) ausgewählt .
Der Wert von hash(float('inf'))
ist einer der systemabhängigen Parameter der integrierten Hash-Funktion für numerische Typen und ist auch wie sys.hash_info.inf
in Python 3 verfügbar :
>>> import sys
>>> sys.hash_info
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003, algorithm='siphash24', hash_bits=64, seed_bits=128, cutoff=0)
>>> sys.hash_info.inf
314159
(Gleiche Ergebnisse auch mit PyPy .)
In Bezug auf Code hash
ist eine integrierte Funktion. Wenn Sie es für ein Python-Float-Objekt aufrufen, wird die Funktion aufgerufen, deren Zeiger durch das tp_hash
Attribut des integrierten Float-Typs ( PyTypeObject PyFloat_Type
) angegeben wird. Dies ist die float_hash
Funktion, die als definiert istreturn _Py_HashDouble(v->ob_fval)
und die wiederum hat
if (Py_IS_INFINITY(v))
return v > 0 ? _PyHASH_INF : -_PyHASH_INF;
wo _PyHASH_INF
ist definiert als 314159:
#define _PyHASH_INF 314159
In Bezug auf die Geschichte wurde die erste Erwähnung 314159
in diesem Zusammenhang im Python-Code (Sie finden diese mit git bisect
oder git log -S 314159 -p
) von Tim Peters im August 2000 in dem jetzt im Git-Repository festgeschriebenen Commit 39dce293 hinzugefügtcpython
.
Die Festschreibungsnachricht lautet:
Fix für http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470 . Dies war ein irreführender Fehler - der wahre "Fehler" war, dass hash(x)
ein Fehler zurückgegeben wurde, wenn x
eine Unendlichkeit vorliegt . Das wurde behoben. Neues Py_IS_INFINITY
Makro hinzugefügt zu
pyport.h
. Neu angeordneter Code, um die zunehmende Doppelarbeit beim Hashing von Float und komplexen Zahlen zu reduzieren und Trents früheren Versuch zu einer logischen Schlussfolgerung zu führen. Es wurde ein äußerst seltener Fehler behoben, bei dem das Hashing von Floats -1 zurückgeben konnte, selbst wenn kein Fehler auftrat (es wurde keine Zeit damit verschwendet, einen Testfall zu erstellen, es war einfach aus dem Code ersichtlich, dass dies passieren konnte ). Verbesserter komplexer Hash,
hash(complex(x, y))
der nicht hash(complex(y, x))
mehr systematisch gleich ist.
Insbesondere in diesem Commit riss er den Code von static long float_hash(PyFloatObject *v)
in heraus Objects/floatobject.c
und machte es gerecht return _Py_HashDouble(v->ob_fval);
, und in der Definition von long _Py_HashDouble(double v)
in Objects/object.c
fügte er die Zeilen hinzu:
if (Py_IS_INFINITY(intpart))
/* can't convert to long int -- arbitrary */
v = v < 0 ? -271828.0 : 314159.0;
Wie bereits erwähnt, war dies eine willkürliche Entscheidung. Beachten Sie, dass 271828 aus den ersten Dezimalstellen von e gebildet wird .
Verwandte spätere Commits:
Von Mark Dickinson im April 2010 ( auch ), wodurch sich der Decimal
Typ ähnlich verhält
Von Mark Dickinson im April 2010 ( ebenfalls ), der diesen Scheck nach oben verschiebt und Testfälle hinzufügt
Von Mark Dickinson Mai 2010 als Ausgabe 8188 , vollständig die Hash - Funktion zum Umschreiben seiner aktuellen Implementierung , aber diesen speziellen Fall zu halten, was die konstanten einen Namen _PyHASH_INF
(auch die 271.828 zu entfernen, weshalb in Python 3 hash(float('-inf'))
zurückkehrt , -314159
anstatt -271828
wie es funktioniert in Python 2)
Von Raymond Hettinger im Januar 2011 , indem er in "Was ist neu" für Python 3.2 ein explizites Beispiel für die Anzeige des sys.hash_info
obigen Werts hinzufügt . (Siehe hier .)
Von Stefan Krah im März 2012, der das Dezimalmodul modifiziert, aber diesen Hash beibehält.
Von Christian Heimes im November 2013 wurde die Definition von _PyHASH_INF
von dort Include/pyport.h
, Include/pyhash.h
wo sie jetzt lebt , verschoben .
hash(float('nan'))
es ist0
.