Chaoswind hat geschrieben:
Ist es doch. Was hat das Eine mit dem Anderen zu tun?
Weil ein Objekt sich um seine innereien zu kümmern hat, nicht irgendeine Funktion.
Wer (spezielle) Methoden "dispatched", das Objekt oder der Interpreter, entscheidet nicht darüber ob die Sprache objektorientiert ist oder nicht. Sonst wären Sprachen, die so etwas schon zur Übersetzungszeit festlegen (C++, FreePascal/Delphi) oder solche die keinen Eingriff in die Nachrichtenweiterleitung erlauben (Java, C#) nicht objektorientiert. (Ich persönlich finde Python oder ObjektiveC aber auch "schöner".)
In den Attributen der Klasse, resp. der Klasse. Schlägt das fehl wird __getattr__ aufgerufen, welches den Fall behandelt.
Ok, dann gibt es also noch einen Aufruf
vor __getattribute___. Dann bleibt die Frage warum nach diesem Aufruf nicht __getattribute__ abgefragt wird, den __getitem__ und __add__ existieren in dem beispiel nicht.
Die Spezialmethoden werden wahrscheinlich intern nochmal in einem Feld gehalten, damit schnellerer Code für die Operatoren erzeugt werden kann. Dann braucht man nämlich nicht über's `__dict__` zu gehen, sondern kann direkt per Offset auf die Methode zugreifen.
Es gibt bei CPython eigene Opcodes im Bytecode für die Operatoren/Spezialmethoden. Das erklärt warum bei ``a.__add__(b)`` dann doch wieder `__getattribute__()` aufgerufen wird:
Code: Alles auswählen
In [140]: def test1(a, b):
.140.: return a + b
.140.:
In [141]: def test2(a, b):
.141.: return a.__add__(b)
.141.:
In [142]: import dis
In [143]: dis.dis(test1)
2 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 BINARY_ADD
7 RETURN_VALUE
In [144]: dis.dis(test2)
2 0 LOAD_FAST 0 (a)
3 LOAD_ATTR 1 (__add__)
6 LOAD_FAST 1 (b)
9 CALL_FUNCTION 1
12 RETURN_VALUE
Bei dem ``LOAD_ATTR`` wird die Klasse befragt.
Die Spezialmethoden werden übrigens auch immer von der Klasse abgefragt und nicht beim Objekt. Man kann sie also auch nicht nur für ein einzelnes Objekt überschreiben, immer nur bei der Klasse.