Ich möchte in der Lage sein zu testen, ob zwei aufrufbare Objekte identisch sind oder nicht. Ich würde die Identitätssemantik bevorzugen (mit dem "is" -Operator), aber ich habe entdeckt, dass, wenn Methoden involviert sind, etwas anderes passiert.Wie sollten Funktionen auf Gleichheit oder Identität getestet werden?
#(1) identity and equality with a method
class Foo(object):
def bar(self):
pass
foo = Foo()
b = foo.bar
b == foo.bar #evaluates True. why?
b is foo.bar #evaluates False. why?
Ich habe dies sowohl mit Python reproduziert 2.7 und 3.3 (CPython), um sicherzustellen, es ist nicht ein Implementierungsdetail der älteren Version. In anderen Fällen arbeitet Identitätsprüfung als (Interpreter-Sitzung von oben fortgesetzt) erwartet:
#(2) with a non-method function
def fun(self):
pass
f = fun
f == fun #evaluates True
f is fun #evaluates True
#(3) when fun is bound as a method
Foo.met = fun
foo.met == fun #evaluates False
foo.met is fun #evaluates False
#(4) with a callable data member
class CanCall(object):
def __call__(self):
pass
Foo.can = CanCall()
c = foo.can
c == foo.can #evaluates True
c is foo.can #evaluates True
Nach der Frage How does Python distinguish callback function which is a member of a class?, eine Funktion eingewickelt wird, wenn als Methode gebunden. Dies ist sinnvoll und entspricht dem obigen Fall (3).
Gibt es eine zuverlässige Möglichkeit, eine Methode an einen anderen Namen zu binden und sie dann später gleich wie ein aufrufbares Objekt oder eine einfache Funktion vergleichen zu lassen? Wenn das "==" funktioniert, wie funktioniert das? Warum verhalten sich "==" und "ist" im obigen Fall (1) anders?
bearbeiten
Wie @Claudiu darauf hingewiesen, ist die Antwort auf Why don't methods have reference equality? auch die Antwort auf diese Frage.
Haben Sie das gesehen? http://stackoverflow.com/questions/306313/python-is-operator-behaves-unexpectedly-with-integers Ich denke, es könnte ein wenig helfen, zu verstehen, warum dies passiert. – taronish4
Interessante Fragen, danke für das Posten. (+1) – NPE
Ja kurz gesagt, es ist, weil beim Aufrufen von 'is' es nach der ID und nicht nach dem Wert selbst sucht und zwei instanzierte Objekte nicht die gleiche ID haben, verglichen mit' == 'überprüft es den Wert der Objekt und nicht nur eine schnelle ID-Prüfung. – Torxed