python - 了解 __init_subclass__

标签 python class subclass python-3.6 metaclass

我终于升级了我的 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/

相关文章:

python - 如何键入具有封闭类类型的提示方法?

python - 如何在 Pandas 中用 NaN 替换浮点值?

python - 如何使用 python 以编程方式创建 Google 表单?是否可以通过应用程序脚本和 python 接口(interface)或类似的东西来做到这一点?

c++ - 直接和复制构造函数

c++ - 创建子类的多个实例,只有一个父类(super class)的实例

python - 我可以在 Windows 中通过 ctrl-D 而不是 ctrl-Z 退出 Python 2.5 吗?

php - ZipArchive php 类 - 它是 PHP 内置的吗?

typescript - 如何在 typescript 中使用静态方法扩展和键入导入的类

ios - UIView 子类的大小取决于设备

java - 重写返回 T 的泛型父类(super class)的方法