[解決済み] __init_subclass__ を理解する
質問
私はついに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__
の中に
記述子クラス
のインスタンスを持つクラスは、メタクラスを使用することに置き換わります。
ディスクリプタを属性として持つ
.
関連
-
[解決済み] スライス表記を理解する
-
[解決済み] dict.copy()を理解する - 浅いか深いか?
-
[解決済み] Python __call__ 特殊メソッド実践例
-
[解決済み] データフレームをソートした後にインデックスを更新する
-
[解決済み] Django Rest Framework ファイルアップロード
-
[解決済み] if 節の終了方法
-
[解決済み] 単純な文字列からtimedeltaオブジェクトを作成する方法
-
[解決済み] 認証プラグイン 'caching_sha2_password' はサポートされていません。
-
[解決済み] Pythonでリストが空かどうかをチェックする方法は?重複
-
[解決済み] Alembicアップグレードスクリプトでインサートやアップデートを実行するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】名前が与えられたクラスのすべてのサブクラスを見つけるには?
-
[解決済み] Pythonのキャッシュライブラリはありますか?
-
[解決済み] Pythonでコード行間にかかる時間を測定するには?
-
[解決済み] SQLAlchemy: 日付フィールドをフィルタリングする方法は?
-
[解決済み] データフレームをソートした後にインデックスを更新する
-
[解決済み] Django Rest Framework ファイルアップロード
-
[解決済み] ファブリック経由でデプロイユーザとしてvirtualenvを有効化する
-
[解決済み] スペースがないテキストを単語のリストに分割する方法
-
[解決済み] 範囲指定された浮動小数点数のランダムな配列を生成します。
-
[解決済み] virtualenv の `--no-site-packages` オプションを元に戻す。