1. ホーム
  2. python

[解決済み] クラスがサブクラス化されたときにコードを実行するには?重複

2022-06-15 03:24:26

質問

自分のクラスがサブクラス化されたときに、コードをトリガーする方法はありますか?

class SuperClass:
    def triggered_routine(subclass):
        print("was subclassed by " + subclass.__name__)

magically_register_triggered_routine()

print("foo")

class SubClass0(SuperClass):
    pass

print("bar")

class SubClass1(SuperClass):
    print("test")

出力すべき

foo
was subclassed by SubClass0
bar
test
was subclassed by SubClass1

どのように解決するのですか?

クラスは(デフォルトでは)インスタンスとして type . クラスのインスタンスと同じように Foo によって作成されます。 foo = Foo(...) , のインスタンスは type (すなわちクラス) は myclass = type(name, bases, clsdict) .

もし、クラスが作られた瞬間に何か特別なことを起こしたいのであれば、 クラスを作るものを変更しなければなりません -- すなわち type . のサブクラスを定義することです。 type のサブクラス -- すなわちメタクラスを定義することです。

メタクラスは、クラスがそのインスタンスにそうであるように、そのクラスにそうである。

Python2では、クラスのメタクラスは

class SuperClass:
    __metaclass__ = Watcher

ここで Watcher のサブクラスです。 type .

Python3では、構文は次のように変更されました。

class SuperClass(metaclass=Watcher)

と等価である。

Superclass = Watcher(name, bases, clsdict)

ここで、この場合 name は文字列 'Superclass' となり、かつ bases はタプル (object, ) . は clsdict は、クラス定義の本文で定義されたクラス属性の辞書です。

と似ていることに注意してください。 myclass = type(name, bases, clsdict) .

というわけで、ちょうどクラスの __init__ を使ってインスタンスが生成される瞬間のイベントを制御するのと同様に、クラスが生成される瞬間のイベントをメタクラスの __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")

プリント

foo
was subclassed by SubClass0
bar
test
was subclassed by SubClass1