我终于升级了我的 python 版本,并且发现了添加的新功能。除其他外,我对新的 __init_subclass__
摸不着头脑。方法。来自文档:
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.
所以我开始尝试使用它,按照文档中的示例进行操作:
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文章也是如此,但对我帮助不大。这种方法在哪里有帮助?是为了:
- 在创建时注册子类的父类(super class)?
- 强制子类在定义时设置字段?
另外,我是否需要了解 __set_name__
完全理解它的用法?
最佳答案
PEP 487着手采用两个常见的元类用例并使它们更易于访问,而无需了解元类的所有来龙去脉。 __init_subclass__
和 __set_name__
这两个新功能在其他方面独立,它们不相互依赖。
__init_subclass__
只是一个钩子(Hook)方法。你可以用它做任何你想做的事。它对于以某种方式注册子类都很有用, 和 用于在这些子类上设置默认属性值。
我们最近使用它来为不同的版本控制系统提供“适配器”,例如:
class RepositoryType(Enum):
HG = auto()
GIT = auto()
SVN = auto()
PERFORCE = auto()
class Repository():
_registry = {t: {} for t in RepositoryType}
def __init_subclass__(cls, scm_type=None, name=None, **kwargs):
super().__init_subclass__(**kwargs)
if scm_type is not None:
cls._registry[scm_type][name] = cls
class MainHgRepository(Repository, scm_type=RepositoryType.HG, name='main'):
pass
class GenericGitRepository(Repository, scm_type=RepositoryType.GIT):
pass
这让我们可以轻松地为特定存储库定义处理程序类,而无需使用元类或装饰器。
关于python - 了解 __init_subclass__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45400284/