我不认为拥有它很重要,因为真正的实现无论如何都将在每个子类中实现。请考虑以下代码:
class Cat:
def __init__(self, breed):
self.breed = breed
def sound(self): # having this or not does'nt make any difference
pass
class Angora(Cat):
def sound(self):
print("miau")
class Scotish(Cat):
def sound(self):
print('meowww')
a = Angora('angora')
b = Scotish('scotish')
cats = [a, b]
for catt in cats:
catt.sound()
我现在必须遗漏一些东西,因为我很难理解这个词。
答案 0 :(得分:2)
你需要这样的东西,所以如果你忘了在任何子类中实现该方法,你会看到异常。
class Cat:
def __init__(self, breed):
self.breed = breed
def sound(self):
raise NotImplementedError('Should be implemented in subclass')
此外,它使类接口更清晰。
答案 1 :(得分:1)
即使不需要使代码工作,也有助于使代码自我记录,以便将来更容易实现Cat。我还可以在Cat对象上使用内省/反射。 另请参阅在此处向python添加“正确”抽象基类的动机:https://www.python.org/dev/peps/pep-3119/
答案 2 :(得分:1)
放置一个将被覆盖的空方法,没有多少意义,但如果Cat
是一个实际的抽象类,而sound
是一个强制的方法要被覆盖,那么它有很大的好处,例如:
import abc
class Cat(abc.ABC):
def __init__(self, breed):
self.breed = breed
@abc.abstractmethod
def sound(self): # having this as an abstract method DOES make a difference
pass
class Scotish(Cat):
def sonud(self):
print('meowww')
您是否注意到拼写错误,尝试初始化Scotish
时会出现此错误:
>>> b = Scotish("scotish")
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
b = Scotish("scotish")
TypeError: Can't instantiate abstract class Scotish with abstract methods sound
所以,在你得到任何奇怪的模糊错误之前,你会立刻得到实际出错的地方!
与简单的raise NotImplementedError
不同,抽象方法可以包含很好的抽象代码!就像函数可能做的一个例子一样,一个很好的例子是_collections_abc.Generator.throw
:
@abstractmethod
def throw(self, typ, val=None, tb=None):
"""Raise an exception in the coroutine.
Return next yielded value or raise StopIteration.
"""
if val is None:
if tb is None:
raise typ
val = typ()
if tb is not None:
val = val.with_traceback(tb)
raise val
这不是真正的代码,这不是生成器实际处理throw
方法的方式,但它是如何至少处理参数的一个很好的抽象!
答案 3 :(得分:0)
到目前为止尚未说过的事情:
这是实施open closed principle的声音解决方案的关键要素。
关键点是:通常,您使用抽象基类来实现某种行为......对于所有子类应该是相同的。另一方面,这种“常见”实现可能需要调用子类特定方法才能完成其工作。
一些伪代码示例:
abstract class Base:
final foo():
return "foo" + infoFromChild()
abstract infoFromChild()
然后:
但当然:这些东西在Java或C ++等“更静态”的语言中更具“意义”。在python中,你可能会以不同的方式做事。