Bei zwei Objekten wird nicht garantiert, dass sie auf den gleichen Wert synchronisiert werden, es sei denn, sie vergleichen [1].
Python-Funktionen (einschließlich lambdas) vergleichen nicht gleich, auch wenn sie den gleichen Code haben [2]. Zum Beispiel:
>>> (lambda: 1) == (lambda: 1)
False
Implementierungsweise ist dieses Verhalten auf die Tatsache zurückzuführen, dass Funktionsobjekte ihren eigenen Gleichheitsoperator nicht bereitstellen. Stattdessen erben sie den Standardnamen, der die Identität des Objekts verwendet, d. H. Seine Adresse. Von den documentation:
Wenn kein __cmp__()
, __eq__()
oder __ne__()
Betrieb definiert ist, Klasse Instanzen von Objektidentität verglichen („Adresse“).
Hier ist, was in Ihrem speziellen Beispiel passiert:
fn = lambda: 1 # New function is allocated at address A and stored in fn.
fn = lambda: 1 # New function is allocated at address B and stored in fn.
# The function at address A is garbage collected.
fn = lambda: 1 # New function is allocated at address A and stored in fn.
# The function at address B is garbage collected.
fn = lambda: 1 # New function is allocated at address B and stored in fn.
# The function at address A is garbage collected.
...
Da Adresse A
immer auf einen Wert gehasht wird, und die Adresse B
zum anderen, Sie hash(fn)
wechseln zwischen den beiden Werten sehen. Dieses alternierende Verhalten ist jedoch ein Implementierungsartefakt und könnte sich eines Tages ändern, wenn beispielsweise der Garbage Collector etwas anders verhalten würde.
Die folgende interessante Notiz wird von @ruakh beigetragen worden:
Es ist erwähnenswert, dass es nicht möglich ist äquivalent ein allgemeines Verfahren zu bestimmen, ob zwei Funktionen zu schreiben. (Dies ist eine Folge der undecidability der halting problem.) Darüber hinaus kann zwei Python-Funktionen anders verhalten können, selbst wenn ihr Code identisch ist (da sie Verschlüsse sein können mit Bezug distinct-but-gleichnamigen Variablen). Es macht also Sinn, dass Python-Funktionen den Gleichheitsoperator nicht überlasten: Es gibt keine Möglichkeit, etwas besser als die Standard-Objektidentität Vergleich zu implementieren.
[1] Die Umkehrung ist im Allgemeinen nicht wahr: Zwei Objekte, die ungleich vergleichen, können denselben Hash-Wert haben. Dies wird hash collision genannt. würde natürlich immer geben den gleichen Wert, da hash(1)
ist immer gleich innerhalb eines Programms
[2] Aufruf Ihre lambdas und dann das Ergebnis Hashing:
>>> (lambda: 1)() == (lambda: 1)()
True
Nur um klar zu sein, Sie erkennen, dass Sie das eigentliche Funktionsobjekt selbst hashing, Sie Hashing nicht den Wert, den es zurückgeben würde, wenn sie aufgerufen wird, nicht wahr? –
Es ist wahrscheinlich eine schlechte Idee, aber Sie könnten nur das Code-Objekt in Betracht ziehen: 'Hash ((Lambda: 1) .__ Code __)' – berdario
nur neugierig ... welche Modelle würden Sie für diese Funktionalität benötigen? Suchst du Dinge in Wörterbüchern, die auf einer beliebigen Funktion basieren? –