[英]Can a parent's class method call an abstract method which will be implemented in a child class?
如果我有一个父母 class 有两种方法:
class Parent():
@abstractmethod
@staticmethod
def functionA():
pass
def functionB():
return __class__.functionA() + 1
我实现了一个孩子 class:
class Child(Parent):
def functionA(): # this function is different for each kind of child
return 3
最后,子类的目的只是调用functionB()
。 它有效吗? 当然,我可以将functionB()
放入子 class 并使其工作,但是因为functionB()
对于每种子 class 都是相同的,我不想为每个 ZA2F2ED4F8EBC2CBB4C21A29DC40 编写重复代码?
另外,我在这里使用__class__
合适吗?
首先, functionB
本身应该是一个 class 方法。
@classmethod
def functionB(cls):
return cls.functionA() + 1
其次,您仍然必须在每个子 class 中将functionA
装饰为 static 方法; 否则,您将用实例方法替换继承的 static 方法。
class Child(Parent):
@staticmethod
def functionA():
return 3
这是一个工作版本:
from abc import ABC, abstractmethod
class Parent(ABC):
@staticmethod # not needed, but is documentation
@abstractmethod
def a(): pass
@classmethod
def b(cls): return cls.a() + 1
class Child(Parent):
@staticmethod
def a(): return 3
我们可以测试一下:
>>> c = Child()
>>> c.b()
4
值得注意的事情:
我们需要使用ABC
基础 class(或ABCMeta
元类)才能访问abstractmethod
装饰器,如abc
模块文档中所述。
__class__
不是关键字; 它是对象的属性。 我们不能只做__class__.a()
之类的事情,因为没有什么可以从__class__
中获取。 我们可以使用普通方法的self
参数来解决这个问题,但我们在这里真正想要做的是获得不需要实例的行为,但取决于我们使用的派生 class 。 这就是classmethod
的用途,以及为什么有单独的classmethod
和staticmethod
装饰器。
当您使用classmethod
时, class 将作为参数传递,就像您使用普通方法时如何传递实例一样。 按照惯例,我们将其命名为cls
。 有关classmethod
的更多信息,请参阅Raymond Hettinger 的精彩演讲(在 Python 开发团队中) 。
我们的抽象方法的实现也必须在子类中进行装饰,因为它们仍然不是普通的方法——所以 Python 需要知道不要传递实例。
出于技术原因,需要首先列出抽象方法上的staticmethod
方法修饰,在abstractmethod
方法修饰之前。 它在这里实际上什么都不做。 当我们调用例如Parent.a()
时, abstractmethod
方法已经表现得像一个staticmethod
方法(没有实例;我们无论如何都不能创建一个,因为它是一个抽象类)。
对于a
方法,我们也可以使用classmethod
而不是staticmethod
。 这将允许Child
的子级继承Child
行为,而无需显式编写自己的a
实现。 在这种情况下,我们希望在基本抽象方法上显式地修饰classmethod
,而不是staticmethod
; 当然,我们需要为每个a
添加cls
参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.