了解__init_subclass__ [英] Understanding __init_subclass__
问题描述
我终于升级了我的python版本,发现了新功能.除其他事项外,我为新的 __init_subclass__
方法.从文档中:
I finally upgraded my python version and I was discovering the new features added. Among other things, I was scratching my head around the new __init_subclass__
method. From the docs:
只要包含类被子类化,就会调用此方法. cls 然后是新的子类.如果定义为普通实例方法,则此 方法隐式转换为类方法.
This method is called whenever the containing class is subclassed. cls is then the new subclass. If defined as a normal instance method, this method is implicitly converted to a class method.
因此,按照文档中的示例,我开始进行一些操作:
So I started to playing around with it a little bit, following the example in the 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 文章也是,但是对我没有多大帮助.这种方法在哪里有帮助?它用于:
I understand that this method is called after the subclass definition, but my questions are particularly about the usage of this feature. I read the PEP 487 article as well, but didn't help me much. Where would this method be helpful? Is it for:
- 在创建时注册子类的超类?
- 强制子类在定义时设置字段?
此外,我是否需要了解 __set_name__
完全了解其用法?
Also, do I need to understand the __set_name__
to fully comprehend its usage?
推荐答案
__init_subclass__
和__set_name__
是正交机制-它们并不相互绑定,仅在同一PEP中进行了描述.两者都是以前需要全功能元类的功能. PEP 487解决了元类最常见的用法 2 :
__init_subclass__
and __set_name__
are orthogonal mechanisms - they're not tied to each other, just described in the same PEP. Both are features that needed a full-featured metaclass before. The PEP 487 addresses 2 of the most common uses of metaclasses:
- 如何让父母知道何时将其子类化(
__init_subclass__
) - 如何让描述符类知道其用于(
__set_name__
)的属性的名称
- how to let the parent know when it is being subclassed (
__init_subclass__
) - how to let a descriptor class know the name of the property it is used for (
__set_name__
)
正如PEP所说:
尽管有许多种使用元类的方法,但大多数用例仅分为三类:一些初始化代码在类创建后运行,描述符的初始化以及保持类属性的顺序定义.
可以通过对类的创建进行简单的钩子轻松地实现前两个类别:
The first two categories can easily be achieved by having simple hooks into the class creation:
- 一个
__init_subclass__
钩子,用于初始化给定类的所有子类. - 在创建类时,在类中定义的所有属性(描述符)上调用一个
__set_name__
钩子,并且
- An
__init_subclass__
hook that initializes all subclasses of a given class. - upon class creation, a
__set_name__
hook is called on all the attribute (descriptors) defined in the class, and
第三类是另一个PEP的主题, PEP 520 .
The third category is the topic of another PEP, PEP 520.
还请注意,虽然__init_subclass__
替代了在此类的继承树中使用元类,但__set_name__
在 descriptor类中却替代了使用具有 descriptor实例作为属性的类的元类.
Notice also, that while __init_subclass__
is a replacement for using a metaclass in this class's inheritance tree, __set_name__
in a descriptor class is a replacement for using a metaclass for the class that has an instance of the descriptor as an attribute.
这篇关于了解__init_subclass__的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!