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文件。