2016-09-29 2 views
1

Es gibt eine magische Methode namens __ne__ in Python, die auf Objekte != Vergleich ausgelöst wird.Python 2.7 Was verglichen wird, wenn __ne__ nicht definiert ist

Beispiel:

class A(object): 
    def __init__(self, a): 
     self.a = a 

    def __ne__(self, other): 
     return self.a != other.a 

A(3) != A(3) # produces False 
A(3) != A(2) # produces True 

Die Frage:

Was passiert, wenn __ne__ unter der Haube passiert, ist nicht definiert?

Hinweis: In Python 3.x != Vergleich definiert wird, gleich welcher __eq__ kehrt umkehren werden.

Ich dachte, dass Objekt-IDs verglichen werden, in diesem Fall unter der Annahme, dass wir kein Singleton haben, müssten alle != Vergleiche True zurückgeben. Aber anscheinend hat der gleiche Code in verschiedenen Umgebungen unterschiedliche Ergebnisse produziert, also denke ich, es gibt etwas anderes, das anstelle von Objekt-IDs verglichen wird.

Antwort

2

Wenn Sie in Ihrer Klassendefinition nicht explizit __ne__ verwenden, wird __ne__ von geerbt object verwendet. Es funktioniert wie Code folgenden (aber natürlich original in C geschrieben):

def __ne__(self, other): 
    eq_result = self == other 
    if eq_result is NotImplemented: 
     return NotImplemented 
    else: 
     return not eq_result 

So, da Sie benutzerdefinierte Klassen sind zu vergleichen, dann id verwendet wird.

Hier ist der Quellcode source code. Schauen Sie sich slot_tp_richcompare an.

+0

Woher haben Sie es genommen? Haben Sie einen Link zur C-Implementierung dieser Funktionalität? – vovaminiof

+0

@vovaminiof bearbeitet. – turkus

1

Die Antwort von turkus ist korrekt: Wenn keine Methode __ne__() angegeben ist, wird die Umkehrung des Ergebnisses der Methode __eq__() zurückgegeben. Der relevante Teil der CPython Quelle slot_tp_richcompare():

static PyObject * 
slot_tp_richcompare(PyObject *self, PyObject *other, int op) 
{ 
    PyObject *res; 

    if (Py_TYPE(self)->tp_richcompare == slot_tp_richcompare) { 
     res = half_richcompare(self, other, op); 
     if (res != Py_NotImplemented) 
      return res; 
     Py_DECREF(res); 
    } 
    if (Py_TYPE(other)->tp_richcompare == slot_tp_richcompare) { 
     res = half_richcompare(other, self, _Py_SwappedOp[op]); 
     if (res != Py_NotImplemented) { 
      return res; 
     } 
     Py_DECREF(res); 
    } 
    Py_INCREF(Py_NotImplemented); 
    return Py_NotImplemented; 
} 

__ne__() Wenn nicht das Gegenteil Verfahren (definiert in _Py_SwappedOp[op] als Py_EQ, d.h. __eq__(), für Py_NE) definiert ist, genannt. Ein Kommentar in classobject.c zeigt, was sollte geschieht __eq__() nicht definiert werden:

/* Wenn keine __eq__ und keine __cmp__ Methode ist, hash wir auf der Adresse. Wenn eine __eq__ oder __cmp__ Methode existiert, muss eine __hash__ sein. */

Verwandte Themen