使用 ABCMeta.register

问题描述

ABCMetaregister 方法有什么用?

https://docs.python.org/3/library/abc.html

似乎如果我有一个抽象基类 ABC,比如 Animal,我可以使用 register 注册它的子类:

from abc import ABC

class Animal(ABC):
    pass

@Animal.register
class Dog:
    pass

但这与将子类定义为继承自基类是否完全相同?

class Dog(Animal): # same as wrapping with Animal.register decorator?
    pass

换句话说,它只是一种动态定义继承的方式吗?或者我错过了这个方法所做的一些事情?

解决方法

如果您来自一种具有不同 OOP 风格的语言,那么虚拟基类的概念可能看起来很有趣。

寄存器的文档中有一个小例子,恕我直言解释了虚拟基类的概念

from abc import ABC

class MyABC(ABC):
    pass

MyABC.register(tuple)

assert issubclass(tuple,MyABC)
assert isinstance((),MyABC)

代码片段末尾的断言提出以下问题:

  1. 类型 tupleMyABC 的子类型吗。
  2. 文字 ()MyABC 的实例吗。

由于 tuple 是一个内置类并且您不能重新定义它,这些断言应该会失败,它们不会因为 ABCMeta.register “使”issubclassisinstance相信您在没有实际继承发生时修改了 tuple 类型以从 MyABC 继承。

对此有多种用例,您应该查看collections.abc module