Python中的抽象方法
我在使用Python的inheritance时遇到了麻烦。 虽然这个概念在Java中对我来说似乎太简单了,但到目前为止我还是无法理解Python,至less对我来说这是令人惊讶的。
我有一个原型如下:
class Shape(): def __init__(self, shape_name): self.shape = shape_name class Rectangle(Shape): def __init__(self, name): self.shape = name
在上面的代码中,我怎么能做一个抽象的方法,需要实现所有的子类?
沿着这些线,使用ABC
import abc class Shape(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def method_to_implement(self, input): """Method documentation""" return
另外阅读这个很好的教程: http : //www.doughellmann.com/PyMOTW/abc/
你也可以看看在python中引入ABC之前使用的zope.interface 。
在引入abc之前,你会经常看到这个。
class Base(object): def go(self): raise NotImplementedError("Please Implement this method") class Specialized(Base): def go(self): print "Consider me implemented"
查看abc模块 。 基本上,你可以在类上定义__metaclass__ = abc.ABCMeta
,然后用@abc.abstractmethod
方法来修饰每个抽象方法。 从这个类派生的类不能被实例化,除非所有的抽象方法都被覆盖。
如果你的类已经使用了一个元类,那么从ABCMeta
派生它而不是type
,你可以继续使用你自己的元类。
一个廉价的替代方法(以及在引入abc
模块之前的最佳实践)是让所有的抽象方法引发一个exception( NotImplementedError
是一个很好的方法),以便派生它的类必须覆盖该方法才有用处。
然而, abc
解决scheme更好,因为它使得这些类不会被实例化(即它“失败得更快”),还因为可以使用super()
方法提供每个方法的默认或基本实现。函数派生类。
你不能用语言原语。 如前所述, abc包在Python 2.6和更高版本中提供了这个function,但是Python 2.5和更早版本没有选项。 abc
软件包不是Python的新function, 相反,它通过添加明确的“这个类是否这样说呢? 检查手动执行的一致性检查,以便在初始化期间导致错误,如果这样的声明是错误的。
Python是一种军事dynamictypes的语言。 它没有指定语言原语来允许你阻止程序编译,因为一个对象不符合types要求; 这只能在运行时被发现。 如果你需要一个子类实现一个方法,那么文档,然后在盲目地调用这个方法,希望它会在那里。
如果它在那里,太棒了,它只是工作; 这就是所谓的鸭子打字 ,你的物体像鸭子一样呱呱叫,以满足界面。 即使self
是调用这样一个方法的对象 ,这也适用,因为基础方法需要特定实现的特性(generics函数),因为self
是一个约定,而不是实际上特殊的东西。
例外是在__init__
,因为当你的初始化器被调用时,派生types的初始化器没有,所以它没有机会把自己的方法装订到对象上。
如果方法没有实现,你会得到一个AttributeError(如果根本不存在的话)或者TypeError(如果这个名字的东西有,但不是函数,或者没有这个签名)。 这取决于你如何处理这个问题 – 要么称它为程序员错误,并让程序崩溃(并且“应该”对于Python开发者来说显而易见的是什么导致了那种错误 – 一个未被满足的鸭接口),或者抓取和处理这些例外,当你发现你的对象不支持你所期望的。 实际上,在很多情况下捕获AttributeError和TypeError非常重要。
抽象基类是深奥的魔法。 我定期用这些东西来实现一些东西,并且对我自己的聪明很惊讶,不久之后我发现自己被自己的聪明所迷惑(这可能只是个人的限制)。
另一种方法(如果你问我,应该在python std库中)做一个装饰器。
def abstractmethod(method): """ An @abstractmethod member fn decorator. (put this in some library somewhere for reuse). """ def default_abstract_method(*args, **kwargs): raise NotImplementedError('call to abstract method ' + repr(method)) default_abstract_method.__name__ = method.__name__ return default_abstract_method class Shape(object): def __init__(self, shape_name): self.shape = shape_name @abstractmethod def foo(self): print "bar" return class Rectangle(Shape): # note you don't need to do the constructor twice either pass r = Rectangle("x") r.foo()
我没有写装饰器。 它发生在我身上的人会有。 你可以在这里find它: http ://code.activestate.com/recipes/577666-abstract-method-decorator/好一个jimmy2times。 请注意,该页面底部的讨论重新devise了装饰器的安全性。 (如果有人这么倾向的话,这可以通过检查模块来解决)。
你必须实现一个抽象基类(ABC)。
检查python文档
您可以使用six和abc来有效地为python2和python3构build一个类,如下所示:
import six import abc @six.add_metaclass(abc.ABCMeta) class MyClass(object): """ documentation """ @abc.abstractmethod def initialize(self, para=None): """ documentation """ raise NotImplementedError
这是它的一个awesomoe文件。