Ich versuche, die schwarze Magie der Metaklasse in Python zu verstehen . AFAIK, Metaklassen können zum Beispiel verwendet werden, um sicherzustellen, dass einige Methoden in abgeleiteten Klassen implementiert sind, aber ich habe ein Problem mit Enkelkindern . Es scheint, dass ich alle erforderlichen abgeleiteten Methoden explizit implementieren muss, auch wenn es keinen Grund (?) Gibt, dies zu tun.
Schau dir das an:
~ $ ipython
Python 3.6.5 (default, Apr 14 2018, 13:17:30)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.3.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: class Meta(type):
...: def __new__(cls, name, bases, body):
...: if 'some_method' not in body:
...: raise AttributeError('some_method should be implemented')
...: return super().__new__(cls, name, bases, body)
...:
...: class Base(metaclass=Meta):
...: def some_method(self):
...: print('Yay')
...:
...: class Derived(Base):
...: pass
...:
...:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-1-51c072cc7909> in <module>()
9 print('Yay')
10
---> 11 class Derived(Base):
12 pass
<ipython-input-1-51c072cc7909> in __new__(cls, name, bases, body)
2 def __new__(cls, name, bases, body):
3 if 'some_method' not in body:
----> 4 raise AttributeError('some_method should be implemented')
5 return super().__new__(cls, name, bases, body)
6
AttributeError: some_method should be implemented
Soweit ich weiß, sollte dies nicht passieren, da some_method
es aus der Base
Klasse wie hier abgeleitet werden sollte:
In [3]: class Base:
...: def some_method(self):
...: print('Yay')
...:
...: class Derived(Base):
...: pass
...:
...:
In [4]: Derived().some_method()
Yay
Dies wird erwartet? Wenn ja, könnten Sie einen Hinweis geben Sie mir wie beheben dieses Verhalten, so würde ich nicht neu zu implementieren Methoden benötigen?
Sie scheinen zu versuchen, das Rad, das das abc
Modul und seinen @abstractmethod
Dekorateur ist, neu zu erfinden . Ich bin mir nicht sicher, warum Sie das tun möchten, aber wenn Sie dies tun, sollten Sie sich die Quelle ansehen (die aus den Dokumenten verlinkt ist).
Ihre Lösung überprüft, ob der erforderliche Name im Hauptteil der Klasse implementiert ist. Das gilt nicht für geerbte Methoden, aber Sie scheinen das zu wissen, also werde ich es nicht erklären. Was Sie wissen möchten, ist: Was können Sie stattdessen tun? Sie müssen explizit nach geerbten Methoden suchen.
Die Art und Weise abc
ist ziemlich einfach: Bevor überprüft wird, ob alle abstrakten Methoden implementiert sind, wird getattr
jede aufgerufen base
. (Der beste Weg, um zu simulieren, was getattr
in der Klasse passieren wird getattr
, ist schließlich anzurufen .) Alles, was dort gefunden wird, muss nicht im Körper erscheinen.
Ihr Anwendungsfall - mit einer statischen einzelnen erforderlichen Methode anstelle eines dynamischen Satzes von Methoden, die aus der Ausgabe eines Dekorateurs gewonnen werden müssen - ist noch einfacher:
if (not any(hasattr(base, 'some_method') for base in bases)
and 'some_method' not in body):
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen