小编典典

了解__init_subclass__

python

我终于升级了python版本,并发现了新功能。除其他外,我正在为新__init_subclass__方法scratch之以鼻。从文档:

只要包含类被子类化,就会调用此方法。那么cls是新的子类。如果定义为普通实例方法,则此方法将隐式转换为类方法。

因此,按照文档中的示例,我开始进行一些操作:

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__才能完全理解其用法?


阅读 183

收藏
2021-01-20

共1个答案

小编典典

__init_subclass__并且__set_name__是正交机制-
它们并不相互关联,只是在同一PEP中进行了描述。两者都是以前需要功能齐全的元类的功能。该PEP 487地址 2 元类最常见的用途:

  • 如何让父母知道何时将其子类化(__init_subclass__
  • 如何让描述符类知道用于(__set_name__)的属性的名称

正如PEP所说:

尽管有很多使用元类的方法,但 绝大多数用例可分为三类:在类创建后运行的一些初始化代码,描述符的初始化以及保持类属性定义的顺序。

通过对类的创建进行简单的挂钩,就可以轻松实现前两个类别:

  • 一个__init_subclass__钩子,用于初始化给定类的所有子类。
  • 创建__set_name__类时,将对类中定义的所有属性(描述符)调用一个钩子,并且

第三类是另一个PEP 520的主题。

还要注意,虽然__init_subclass__可以替换在 此类 的继承树中使用元类,但是__set_name__描述符类
中的替换是针对将 描述符 的实例 作为attribute 的类使用元类。

2021-01-20