Python 3.4+中的多个顺序抽象基类

时间:2018-07-08 12:37:41

标签: python python-3.x abstract-class

以一个常见的车辆继承示例为例,其中VehicleCar是ABC,而后者从前者继承。然后我们有FordMustang不是抽象的,应该继承自Car

所以,我们有

class Vehicle(ABC):

    @abstractmethod
    def abstract_vehicle_method(self):
        pass

大概一切都很好。但是,对于Car类,我不确定它应该只继承自Vehicle还是继承自VehicleABC,如果是,则以什么顺序继承?此外,我想强制在abstract_vehicle_method()和所有此类非抽象类中定义FordMustang,所以我应该在abstract_vehicle_method中重复Car定义还是继承?解决这个问题?

枚举选项:

应该

class Car(Vehicle):
    [...]

class Car(ABC, Vehicle):
    [...]

class Car(Vehicle, ABC):
    [...]

并且(假设第一个是简单起见是正确的)

class Vehicle(ABC):

    @abstractmethod
    def abstract_vehicle_method(self):
        pass

class Car(Vehicle):

    @abstractmethod
    def abstract_vehicle_method(self):
        pass

    # Some car specific defs here

class FordMustang(Car):

    def abstract_vehicle_method(self):
        # Concrete def here

或者只是

class Vehicle(ABC):

    @abstractmethod
    def abstract_vehicle_method(self):
        pass

class Car(Vehicle):

    # Some car specific defs here

class FordMustang(Car):

    def abstract_vehicle_method(self):
        # Concrete def here

1 个答案:

答案 0 :(得分:1)

您可以直接从Vehicle继承;使得Vehicle为“抽象”的元类随其继承。您不需要为这些子类混用ABC

您也不需要重新定义方法。它也被继承,并且具有“抽象性”。

在内部,元类跟踪哪些属性是“抽象的”;只要有,就不能使用该类创建实例。您可以添加更多抽象方法,或者通过为相同名称提供不同的属性,从集合中删除抽象方法。

具体示例的演示:

>>> from abc import ABC, abstractmethod
>>> class Vehicle(ABC):
...     @abstractmethod
...     def abstract_vehicle_method(self):
...         pass
...
>>> type(Vehicle)  # it's an abstract class
<class 'abc.ABCMeta'>
>>> Vehicle.__abstractmethods__  # this set determines what is still abstract
frozenset({'abstract_vehicle_method'})
>>> class Car(Vehicle):
...     pass
...
>>> type(Car)  # still an abstract class
<class 'abc.ABCMeta'>
>>> Car.__abstractmethods__  # still has abstract methods, incl. inherited methods
frozenset({'abstract_vehicle_method'})
>>> class FordMustang(Car):
...     def abstract_vehicle_method(self):
...         pass
...
>>> type(FordMustang)  # still an abstract class
<class 'abc.ABCMeta'>
>>> FordMustang.__abstractmethods__  # but with no abstract methods left
frozenset()
>>> FordMustang()  # so we can create an instance
<__main__.FordMustang object at 0x106054f98>