212 python inheritance abstract
我在使用Python继承时遇到了麻烦.虽然这个概念在Java中对我来说似乎太容易了但到目前为止我一直无法理解Python,至少对我来说这是令人惊讶的.
我有一个原型如下:
class Shape():
def __init__(self, shape_name):
self.shape = shape_name
class Rectangle(Shape):
def __init__(self, name):
self.shape = name
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我如何制作一个需要为所有子类实现的抽象方法?
kev*_*pie 282
在介绍abc之前,你会经常看到这个.
class Base(object):
def go(self):
raise NotImplementedError("Please Implement this method")
class Specialized(Base):
def go(self):
print "Consider me implemented"
Run Code Online (Sandbox Code Playgroud)
pyf*_*unc 239
沿着这些方向,使用ABC
import abc
class Shape(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def method_to_implement(self, input):
"""Method documentation"""
return
Run Code Online (Sandbox Code Playgroud)
另请阅读这篇好教程:http://www.doughellmann.com/PyMOTW/abc/
您还可以查看在python中引入ABC之前使用的zope.interface.
kin*_*all 41
请参阅abc模块.基本上,您__metaclass__ = abc.ABCMeta在类上定义,然后使用装饰每个抽象方法@abc.abstractmethod.除非已覆盖所有抽象方法,否则无法实例化从此类派生的类.
如果你的类已经在使用元类,ABCMeta而不是type从而导出它,你可以继续使用自己的元类.
一个廉价的替代方案(以及abc模块引入之前的最佳实践)是让所有抽象方法只引发异常(NotImplementedError是一个很好的异常),以便从它派生的类必须覆盖该方法才有用.
但是,abc解决方案更好,因为它使这些类完全不被实例化(即,它"更快地失败"),并且还因为您可以使用super()派生类中的函数提供每个方法的默认或基本实现.
你不能用语言原语.正如已经提到的那样,abc包在Python 2.6及更高版本中提供了这个功能,但是Python 2.5及更早版本没有选项.该abc包不是Python的新功能; 相反,它通过添加显式添加功能"这个类说这样做吗?" 检查,手动实现一致性检查,如果错误地进行了这样的声明,则在初始化期间导致错误.
Python是一种激进的动态类型语言.它没有指定语言原语来允许您阻止程序编译,因为对象与类型要求不匹配; 这只能在运行时发现.如果你需要一个子类实现一个方法,记录那个,然后只是盲目地调用该方法,希望它会存在.
如果它在那里,很棒,它只是有效; 这叫做鸭子打字,你的对象就像鸭子一样嘎嘎叫来满足界面.这只是正常,即使self是你调用这样的方法的对象,强制覆盖的目的,由于需要的功能(通用功能)的具体实现方法的基础,因为self一个约定,没有什么实际的特殊.
例外情况是__init__,因为在调用初始化程序时,派生类型的初始化程序没有,因此它还没有机会将自己的方法装订到对象上.
如果没有实现该方法,你将得到一个AttributeError(如果它根本不存在)或一个TypeError(如果有那个名称的东西,但它不是一个函数,或者它没有那个签名).这取决于你如何处理它 - 要么称它为程序员错误并让它崩溃程序(对于python开发人员来说它应该是显而易见的,这会导致那种错误 - 一个未满足的duck接口),或者捕获和处理当您发现您的对象不支持您希望它执行的操作时,这些异常.实际上,捕捉AttributeError和TypeError在很多情况下都很重要.
您可以使用 6 和 abc 有效地为 python2 和 python3 构造一个类,如下所示:
import six
import abc
@six.add_metaclass(abc.ABCMeta)
class MyClass(object):
"""
documentation
"""
@abc.abstractmethod
def initialize(self, para=None):
"""
documentation
"""
raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)
抽象基类是深刻的魔力.我经常使用它们实现一些东西,并且对自己的聪明感到惊讶,不久之后我发现自己完全被自己的聪明所迷惑(尽管这可能只是个人的限制).
另一种方法(如果你问我应该在python std libs中)是做一个装饰器.
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()
Run Code Online (Sandbox Code Playgroud)
我没有写装饰.我刚想到有人会想到的.你可以在这里找到它:http: //code.activestate.com/recipes/577666-abstract-method-decorator/好一个jimmy2times.请注意该页面底部的讨论重新定义装饰器的安全性.(如果有人这么倾向,可以通过检查模块修复).