Warum ist die Wörterbuch-Bestellung nicht-deterministisch?
Ich habe vor kurzem umgestellt von Python 2.7, Python 3.3, und es scheint, dass, während in Python 2 die Bestellung von Wörterbuch-Schlüssel war willkürlich, aber konsequent, in Python 3 die Anordnung der Tasten, der ein Wörterbuch, die mit z.B. vars()
erscheint nicht-deterministisch.
Wenn ich laufen:
class Test(object): pass
parameters = vars(Test)
print(list(parameters.keys()))
in beiden Python 2.7 und Python 3.3, dann:
- Python 2.7 konsequent gibt mir
['__dict__', '__module__', '__weakref__', '__doc__']
- Mit Python 3.3, bekomme ich eine zufällige Reihenfolge – zum Beispiel:
['__weakref__', '__module__', '__qualname__', '__doc__', '__dict__'] ['__doc__', '__dict__', '__qualname__', '__module__', '__weakref__'] ['__dict__', '__module__', '__qualname__', '__weakref__', '__doc__'] ['__weakref__', '__doc__', '__qualname__', '__dict__', '__module__']
Woher kommt dieses nicht-Determinismus kommen? Und warum ist so etwas wie
list({str(i): i for i in range(10)}.keys())
... im Einklang läuft, immer was
['3', '2', '1', '0', '7', '6', '5', '4', '9', '8']
... ?
InformationsquelleAutor Anaphory | 2013-02-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
Update: In Python-3.6,
dict
hat eine neue Implementierung bewahrt, insertion um. Von Python 3.7, diese Reihenfolge-Erhaltung Verhalten ist garantiert:Dies ist das Ergebnis einer security fix von 2012, das war standardmäßig aktiviert in Python 3.3 (nach unten scrollen, um "Sicherheit").
Aus der Ankündigung:
Wie oben erwähnt, die Letzte aktivierte etwas nicht mehr stimmt in Python 3.3.
Siehe auch:
- Objekt.__hash__()
- Dokumentation ("Hinweis" - Kasten).Wenn es absolut notwendig ist, können Sie deaktivieren hash-Randomisierung in den Versionen von Python betroffen von diesem Verhalten durch das setzen des
PYTHONHASHSEED
die environment-variable0
.Ihre Gegenbeispiel:
... tut nicht in der Tat immer das gleiche Ergebnis in Python 3.3, obwohl die Anzahl der verschiedenen Ordnungen beschränkt aufgrund den Weg hash-Kollisionen behandelt werden:
Wie bereits am Anfang dieser Antwort, das ist nicht mehr der Fall in Python 3.6:
{str(i): i for i in range(10)}
?So, wie wir deaktivieren diese Randomisierung?
href="https://docs.python.org/3/using/cmdline.html#envvar-PYTHONHASHSEED" >docs.python.org/3/using/cmdline.html#envvar-PYTHONHASHSEED
InformationsquelleAutor Zero Piraeus
Beachten Sie, dass Python 3.7 noch nicht-deterministische setzt aber. dicts bewahren einlegen Ordnung, aber Sätze nicht. Sätze weisen die gleiche zufällige Verhalten.
python3 -c "print({str(i) for i in range(9)})"
gibt noch unterschiedliche Ergebnisse von einem Lauf zum nächsten.
InformationsquelleAutor Pete Cacioppi