Ich stieß auf ein Problem, das ich nicht verstehe, und es ist ziemlich kompliziert, also gebe ich mein Bestes, um es hier zu brechen. Bitte sehen Sie sich die folgende Implementierung an. Meine Frage ist: Warum ruft die Vaterklasse die __getitem__ Methode ihres Kindes an, anstatt ihr eigenes __getitem__ zu nennen?Python: aufeinanderfolgende __getitem __() Aufrufe in geerbten Klassen?
class Father(object):
''' Father class '''
def __init__(self,name,gender):
print('call __init__ Father')
self._name = name
# trying to call Father's __getitem__ here
self._gender=self[gender]
def __getitem__(self,key):
print('call __getitem__ Father')
return key
class Child(Father):
''' inherited from Father class '''
def __init__(self, name, gender, age=None):
print('call __init__ Child')
super(self.__class__, self).__init__(name, gender)
self._age = age
def __getitem__(self, key):
print('call __getitem__ Child')
if self._name == 'Marie' and self._age == None:
print('I am not sure, how old I am')
return super(self.__class__, self).__getitem__(key)
one=Child('Klaus','male','12')
other=Child('Marie','female')
die Fehlermeldung, die auftreten wird, ist:
call __init__ Child
call __init__ Father
call __getitem__ Child
call __getitem__ Father
call __init__ Child
call __init__ Father
call __getitem__ Child
Traceback (most recent call last):
File "<ipython-input-58-2d97b09f6e25>", line 1, in <module>
runfile('F:/python-workspace/more-fancy-getitem-fix/test.py', wdir='F:/python-workspace/more-fancy-getitem-fix')
File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 601, in runfile
execfile(filename, namespace)
File "C:\Python27\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 66, in execfile
exec(compile(scripttext, filename, 'exec'), glob, loc)
File "F:/python-workspace/more-fancy-getitem-fix/test.py", line 26, in <module>
other=Child('Marie','female')
File "F:/python-workspace/more-fancy-getitem-fix/test.py", line 16, in __init__
super(self.__class__, self).__init__(name, gender)
File "F:/python-workspace/more-fancy-getitem-fix/test.py", line 6, in __init__
self._gender=self[gender]
File "F:/python-workspace/more-fancy-getitem-fix/test.py", line 21, in __getitem__
if self._name == 'Marie' and self._age == None:
AttributeError: 'Child' object has no attribute '_age'
Ich kann dieses Verhalten nicht erwarten. Ich habe versucht, Kind von Vater zu erben, indem ich Funktionalität hinzufügte. Daher ist die obige Syntax notwendig und macht in meinem komplexeren Code Sinn. Das erste Beispiel von einem = Kind ('Klaus', 'männlich', '12') läuft glatt und man kann schon sehen, dass im Konstruktor des Vaters das __getitem__ des Kindes genannt wird. Im zweiten Beispiel von anderen = Kind ('Marie', 'weiblich') kann man sehen, warum dieser umgekehrte Anruf mich beunruhigt. Hier wird der Code nicht ausgeführt, bis self._age = age definiert ist.
Appart von Vorschlägen, wie dieser Anruf umgekehrt nützlich sein könnte und für was es beabsichtigt war, wäre ich sehr dankbar für Lösungen, wie man die eigene __getitem__ Methode in Vater explizit nennt. Nur schreiben
macht leider nicht den Trick und produziert den gleichen Fehler.
Sie sollten 'super (self .__ class__, self)' nie verwenden. Das wird für immer rekursieren, wenn ich eine "Klasse GrandChild (Child): pass" erstelle – Eric
Klarstellung @ Erics Punkt: In Python 3 würden Sie einfach 'super()' verwenden, was einfach und korrekt ist. In Python 2 müssen Sie die Klasse aufrufen, in der die Methode explizit anhand des Namens definiert ist, z. in deinem Code, Super (Child, self), so kann in Vererbungsfällen die "Super" -Magie verfolgen, welche Überladungen bereits aufgerufen wurden. 'self .__ class__' wird sich ändern, basierend auf welcher Ebene in der Vererbungshierarchie, in der Sie sich befinden, und würde nur für den ersten 'Super'-Aufruf korrekt sein; danach würde es die Klasse des Kindes passieren, nicht die Eltern, wie es sollte. – ShadowRanger
Danke für diesen Hinweis, ich dachte, dass diese Syntax allgemeiner ist, und ich würde hier nicht umbenennen müssen, falls ich den Klassennamen der Väter ändern möchte. Hab nicht umgekehrt gedacht. – c3po