Python中的抽象方法
我需要在Python(3.2)中实现类似于abstract protected
的方法:
class Abstract:
def use_concrete_implementation(self):
print(self._concrete_method())
def _concrete_method(self):
raise NotImplementedError()
class Concrete(Abstract):
def _concrete_method(self):
return 2 * 3
定义一个“抽象”方法,仅仅是为了抛出一个NotImplementedError,这样做真的有用吗?
在其他语言中,protected
的方法通常会用下划线开头,那么在Python中给抽象方法加个下划线算不算好习惯呢?
使用抽象基类(abc)会有什么好处吗?
3 个回答
0
基本上,在基类中一个空的方法在这里并不是必要的。你可以这样做:
class Abstract:
def use_concrete_implementation(self):
print(self._concrete_method())
class Concrete(Abstract):
def _concrete_method(self):
return 2 * 3
实际上,在Python中你通常甚至不需要基类。因为所有的调用都是动态解析的,如果这个方法存在,就会被调用;如果不存在,就会出现一个AttributeError
错误。
注意:在文档中提到_concrete_method
需要在子类中实现是很重要的。
10
当你不确定的时候,可以参考Guido的做法。
不要用下划线。只需将“抽象方法”定义为一行代码,并抛出NotImplementedError错误:
class Abstract():
def ConcreteMethod(self):
raise NotImplementedError("error message")
43
在Python中,通常会避免使用这种抽象方法。你可以通过文档来定义一个接口,然后简单地假设传入的对象符合这个接口,这种方式被称为“鸭子类型”。
如果你真的想定义一个带有抽象方法的抽象基类,可以使用abc
模块来实现:
from abc import ABCMeta, abstractmethod
class Abstract(metaclass=ABCMeta):
def use_concrete_implementation(self):
print(self._concrete_method())
@abstractmethod
def _concrete_method(self):
pass
class Concrete(Abstract):
def _concrete_method(self):
return 2 * 3
不过,这并不是Python的常规做法。abc
模块的主要目的之一是引入一种机制来重载isinstance()
,但通常情况下,我们会避免使用isinstance()
检查,而更倾向于使用鸭子类型。如果你确实需要这样做,可以使用它,但不要把它当作定义接口的一般模式。