Python 3.4+;
以一个常见的车辆继承为例,Python 3.4+;,python,python-3.x,abstract-class,Python,Python 3.x,Abstract Class,以一个常见的车辆继承为例,vehicle和Car是ABC,后者从前者继承。然后我们就有了例如福特野马,它不是抽象的,应该继承自汽车 所以,我们有 class Vehicle(ABC): @abstractmethod def abstract_vehicle_method(self): pass 想必这一切都很好。但是,对于Car类,我不确定它是否应该仅从Vehicle继承,还是从Vehicle和ABC继承,如果是,以什么顺序继承?此外,我想强制abstrac
vehicle
和Car
是ABC,后者从前者继承。然后我们就有了例如福特野马
,它不是抽象的,应该继承自汽车
所以,我们有
class Vehicle(ABC):
@abstractmethod
def abstract_vehicle_method(self):
pass
想必这一切都很好。但是,对于Car
类,我不确定它是否应该仅从Vehicle
继承,还是从Vehicle
和ABC
继承,如果是,以什么顺序继承?此外,我想强制abstract\u vehicle\u method()
在FordMustang
和所有此类非抽象类中定义,那么我应该重复abstract\u vehicle\u method
中的abstract\u vehicle\u method
定义,还是继承会解决这个问题
要列举选项,请执行以下操作:
应该是吗
class Car(Vehicle):
[...]
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 Car(Vehicle):
[...]
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
您可以直接从
车辆继承;使车辆
成为“抽象”的元类将与它一起继承。对于这些子类,您不需要混合使用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>
>>从abc导入abc,abstractmethod
>>>车辆等级(ABC):
... @抽象方法
... def abstract_vehicle_方法(自):
... 通过
...
>>>type(Vehicle)#它是一个抽象类
>>>车辆。_uAbstractMethods_#此集合确定什么仍然是抽象的
冻结集({'abstract\u vehicle\u method'})
>>>车辆类别:
... 通过
...
>>>type(Car)#仍然是一个抽象类
>>>Car.uu abstractmethods_uuu#仍然有抽象方法,包括继承的方法
冻结集({'abstract\u vehicle\u method'})
>>>野马(汽车)的等级:
... def abstract_vehicle_方法(自):
... 通过
...
>>>类型(FordMustang)#仍然是一个抽象类
>>>FordMustang.uu abstractmethods_uu35;但没有留下任何抽象方法
frozenset()
>>>FordMustang()#因此我们可以创建一个实例
这完全取决于您想对这些类执行什么操作。你想让Car成为一个抽象类还是想让它用来实例化对象?@OlivierMelançon:不是为了回答这里提到的问题,它不是。我很好奇在实例化抽象类时,TypeError是从哪里产生的。它似乎不是来自abc模块中的任何地方。你知道是什么引起的吗?@OlivierMelançon:这是由对象处理的;看见对于设置了Py\u TPFLAGS\u is\u ABSTRACT
的任何类,都会引发异常。当ABCMeta将\uuuuuuu abstractmethods\uuuuu
设置为非空值时,将设置该标志。谢谢。让我震惊的是,PyCharm认为这是“错误的”,尽管这是有意义的,也是最优雅的方法。对我来说,它给出了一个“类车必须实现所有抽象方法”的代码检查错误。也许我会把它作为一张票向他们提出,让他们去修正,尽管实际上我认为IDE没有办法区分意图的不同,也无法确定某个继承的类是否应该是抽象的,或者用户是否只是忘记了在非抽象类中实现抽象方法。不过,当我混入ABC
时,它也会触发此错误。见图。@P.Lau:这肯定是PyCharm的一个假设,即不能从基类创建抽象类的层次结构,这是错误的。