zajęciach (domyślnie) są instancjami type
. Tak jak instancja klasy Foo
jest tworzona przez foo = Foo(...)
, instancja type
(tj. Klasa) jest tworzona przez myclass = type(name, bases, clsdict)
.
Jeśli chcesz, aby coś szczególnego wydarzyło się w momencie tworzenia klasy, musisz zmodyfikować rzecz tworząc klasę - tj. type
. Sposobem na to jest zdefiniowanie podklasy type
- tj. Metaklasy.
Metaclass jest do swojej klasy, jako klasa do swojej instancji.
W python2 byś zdefiniował metaklasą o klasie
class SuperClass:
__metaclass__ = Watcher
gdzie Watcher
jest podklasą type
.
W Python3 składnia została zmieniona na
class SuperClass(metaclass=Watcher)
Oba są równoważne
Superclass = Watcher(name, bases, clsdict)
gdzie w tym przypadku name
równy ciąg 'Superclass'
i bases
jest krotka (object,)
. clsdict
to słownik atrybutów klas zdefiniowanych w treści definicji klasy. Podaj podobieństwo do myclass = type(name, bases, clsdict)
.
Więc, tak jak byłoby użyć klasy na __init__
kontrolować wydarzenia w momencie tworzenia instancji, można kontrolować wydarzenia w momencie utworzenia klasy jest z metaklasa na __init__
:
class Watcher(type):
def __init__(cls, name, bases, clsdict):
if len(cls.mro()) > 2:
print("was subclassed by " + name)
super(Watcher, cls).__init__(name, bases, clsdict)
class SuperClass:
__metaclass__ = Watcher
print("foo")
class SubClass0(SuperClass):
pass
print("bar")
class SubClass1(SuperClass):
print("test")
drukuje
foo
was subclassed by SubClass0
bar
test
was subclassed by SubClass1
Użyj metaclass; metaclasses są wywoływane podczas tworzenia klas, tak jak klasy są wywoływane podczas tworzenia instancji. –
Nie można dodać odpowiedzi, ale dzisiaj python3.6 ma '__init_subclass__' - sprawdź to! –
@ Orduan: dziękuję, brzmi użytecznie. Może nawet wystarczający powód, aby odznaczać to pytanie jako duplikat, ponieważ istnieje teraz dedykowane rozwiązanie mojego problemu zamiast "używać metaclass". –