我有一个父类,我想“强制”从它继承的每个人都实现一些特定的类属性。
我的方法没有这个问题,因为我创建了一个虚拟方法来引发
NotImplementedError
,这使得它非常清楚。
至于类属性 - 我不想在父类中创建它们并将它们设置为 None,因为这不会强制开发人员在子类中实现它们。
一些代码来演示当前情况:
class Pet(object):
name = None
def make_noise(self):
raise NotImplementedError("Needs to implement in subclass")
def print_my_name(self):
print(self.name)
class Dog(Pet):
# how to force declairing "name" attribute for subclasses?
def make_noise(self):
print("Whof Whof")
在此示例中,开发人员 1 创建了 Pet 类,并希望其他开发人员实现具有“name”属性的子类。 Developer2 实现了一个子类,但不知道他需要实现“name”属性。
是否可以在Python中创建这样的限制?
您可以尝试使用ABCMeta元类或ABC。 之后,您可以使用 @property 的 @abstractmethod。 例如:
from abc import ABC
class Pet(ABC):
@property
@abstractmethod
def name(self):
pass
@abstractmethod
def make_noise(self):
raise NotImplementedError("Needs to implement in subclass")
def print_my_name(self):
print(self.name)
使用此功能,您还可以使用
@name.setter
添加设置器。
我也有这个问题一段时间了。读完@Sheng Zhuang 的评论后,我认为他的建议是正确的选择。
如果
name
是 Pet
使用的属性,并且确实必须为所有 Pet
定义,但不同类型的 Pet
之间可能有所不同,那么处理此问题的正确方法是使用参数输入Pet
的 __init__
功能。
class Pet(object):
def __init__(self, pet_type, name):
self.pet_type = pet_type
self.name = name
def make_noise(self):
raise NotImplementedError("Needs to implement in subclass")
def print_my_pet_type(self):
print(self.pet_type)
def print_my_name(self):
print(self.name)
class Dog(Pet):
def __init__(self, name):
super().__init__(pet_type='dog', name=name)
def make_noise(self):
print("Whof Whof")
我添加了
pet_type
和 name
进行比较。
pet_type
是编写 Dog
的开发人员可以/应该传递给 Pet.__init__
。
name
仍然暴露给 Dog
类的最终用户,他们可以传入任何他们喜欢的内容。
编辑:我认为语义上的缺点是
pet_type
并不是像 name
那样真正的实例属性。目的是所有 Dog
都将具有相同的 pet_type
,因此如果 Pet
能够以某种方式强制所有子类必须将 SubPet.pet_type =
定义为类属性,那么在语义上会更加一致,但考虑到有没有干净的方法来做到这一点,我认为通过 super()
传递的实例属性是正确的方法。
使用可以根据您的要求使用Python的
Abstract Base Class
/ ABS
或Method Overriding
对您来说可行。