1. ホーム
  2. python

[解決済み] __init_subclass__ を理解する

2023-06-24 07:12:46

質問

私はついにpythonのバージョンをアップグレードし、追加された新しい機能を発見していました。とりわけ、私は新しい __init_subclass__ メソッドについて頭を悩ませていました。docsより。

このメソッドは、包含するクラスがサブクラス化されるたびに呼び出されます。 cls は新しいサブクラスとなります。通常のインスタンスメソッドとして定義されている場合、この メソッドは暗黙のうちにクラスメソッドに変換されます。

というわけで、docsの例に従って、ちょっと遊んでみました。

class Philosopher:
    def __init_subclass__(cls, default_name, **kwargs):
        super().__init_subclass__(**kwargs)
        print(f"Called __init_subclass({cls}, {default_name})")
        cls.default_name = default_name

class AustralianPhilosopher(Philosopher, default_name="Bruce"):
    pass

class GermanPhilosopher(Philosopher, default_name="Nietzsche"):
    default_name = "Hegel"
    print("Set name to Hegel")

Bruce = AustralianPhilosopher()
Mistery = GermanPhilosopher()
print(Bruce.default_name)
print(Mistery.default_name)

このような出力をします。

Called __init_subclass(<class '__main__.AustralianPhilosopher'>, 'Bruce')
'Set name to Hegel'
Called __init_subclass(<class '__main__.GermanPhilosopher'>, 'Nietzsche')
'Bruce'
'Nietzsche'

というメソッドがあるそうですが の後に の後に呼び出されることは理解できますが、私の質問は特にこの機能の使用方法についてです。私が読んだのは PEP 487 の記事も読みましたが、あまり役に立ちませんでした。この方法はどこに役立つのでしょうか?のためでしょうか。

  • スーパークラスがサブクラスを作成するときに登録するため?
  • 定義時にサブクラスがフィールドを設定することを強制するか?

また __set_name__ を理解する必要があるのでしょうか?

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

__init_subclass__ そして __set_name__ は直交するメカニズムで、互いに結びついているわけではなく、同じ PEP に記述されているだけです。どちらも、以前はフル装備のメタクラスを必要としていた機能です。PEP 487 では 2 という、メタクラスの最も一般的な使い方を取り上げています。

  • サブクラス化されたときに親に知らせる方法 ( __init_subclass__ )
  • ディスクリプタクラスが使用するプロパティの名前を知らせる方法 ( __set_name__ )

PEPにあるように

メタクラスを利用する方法はたくさん考えられますが、その中でも クラス生成後に実行されるいくつかの初期化コード、ディスクリプタの初期化、そしてクラス属性が定義された順序を維持することです。

最初の2つのカテゴリは、クラス生成への単純なフックを持つことによって簡単に達成することができます。

  • An __init_subclass__ フックで、与えられたクラスのすべてのサブクラスを初期化します。
  • は、クラス作成時に __set_name__ フックが、クラスで定義された全ての属性(ディスクリプタ)に対して呼び出され

3番目のカテゴリは別のPEPのトピックです。 PEP 520 .

また __init_subclass__ でのメタクラス使用の置き換えであることに注意してください。 この クラスの継承ツリーで __set_name__ の中に 記述子クラス のインスタンスを持つクラスは、メタクラスを使用することに置き換わります。 ディスクリプタを属性として持つ .