我在使用Python继承时有麻烦。虽然这个概念在Java中对我来说太简单了,但到目前为止,我还无法理解Python,这至少让我感到惊讶。
我有一个原型如下:
class Shape():
def __init__(self, shape_name):
self.shape = shape_name
class Rectangle(Shape):
def __init__(self, name):
self.shape = name
在上面的代码中,我如何才能使一个抽象方法,需要实现的所有子类?
你不能用语言原语。如前所述,abc包在Python 2.6及更高版本中提供了此功能,但Python 2.5及更早版本中没有此选项。abc包并不是Python的新特性;相反,它通过添加显式的“这个类是否说它这样做?”检查来添加功能,并使用手动实现的一致性检查,如果错误地声明此类声明,则会在初始化期间导致错误。
Python是一种激进的动态类型语言。它没有指定语言原语来阻止程序因为对象不匹配类型要求而被编译;这只能在运行时发现。如果你需要一个子类实现一个方法,记录它,然后只调用这个方法,盲目地希望它会在那里。
如果它在那里,那就太棒了,它就是有效的;这被称为鸭子类型,您的对象已经像鸭子一样嘎嘎叫,以满足接口。即使self是调用此类方法的对象,出于强制重写的目的(由于基本方法需要特性的特定实现(泛型函数)),这也很好,因为self是一种约定,而不是任何实际特殊的东西。
异常出现在__init__中,因为当你的初始化式被调用时,派生类型的初始化式还没有被调用,所以它还没有机会将自己的方法固定到对象上。
If the method was't implemented, you'll get an AttributeError (if it's not there at all) or a TypeError (if something by that name is there but it's not a function or it didn't have that signature). It's up to you how you handle that- either call it programmer error and let it crash the program (and it "should" be obvious to a python developer what causes that kind of error there- an unmet duck interface), or catch and handle those exceptions when you discover that your object didn't support what you wish it did. Catching AttributeError and TypeError is important in a lot of situations, actually.
参见abc模块。基本上,你定义__metaclass__ = abc。ABCMeta,然后用@abc.abstractmethod装饰每个抽象方法。除非重写了所有抽象方法,否则不能实例化从该类派生的类。
如果您的类已经使用了元类,则从ABCMeta而不是type派生它,您可以继续使用自己的元类。
一种廉价的替代方法(也是abc模块引入之前的最佳实践)是让所有抽象方法都引发一个异常(NotImplementedError是一个很好的异常),以便从它派生的类必须重写该方法才能有用。
然而,abc解决方案更好,因为它完全避免了此类类的实例化(即,它“更快地失败”),而且还因为您可以提供每个方法的默认或基本实现,这些方法可以使用派生类中的super()函数实现。
沿着这些线,使用ABC
import abc
class Shape(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def method_to_implement(self, input):
"""Method documentation"""
return
还可以阅读这个很好的教程:https://pymotw.com/3/abc/
你也可以查看zope.interface,它是在python中引入ABC之前使用的。
http://pypi.python.org/pypi/zope.interface
https://zopeinterface.readthedocs.io/en/latest/README.html
你不能用语言原语。如前所述,abc包在Python 2.6及更高版本中提供了此功能,但Python 2.5及更早版本中没有此选项。abc包并不是Python的新特性;相反,它通过添加显式的“这个类是否说它这样做?”检查来添加功能,并使用手动实现的一致性检查,如果错误地声明此类声明,则会在初始化期间导致错误。
Python是一种激进的动态类型语言。它没有指定语言原语来阻止程序因为对象不匹配类型要求而被编译;这只能在运行时发现。如果你需要一个子类实现一个方法,记录它,然后只调用这个方法,盲目地希望它会在那里。
如果它在那里,那就太棒了,它就是有效的;这被称为鸭子类型,您的对象已经像鸭子一样嘎嘎叫,以满足接口。即使self是调用此类方法的对象,出于强制重写的目的(由于基本方法需要特性的特定实现(泛型函数)),这也很好,因为self是一种约定,而不是任何实际特殊的东西。
异常出现在__init__中,因为当你的初始化式被调用时,派生类型的初始化式还没有被调用,所以它还没有机会将自己的方法固定到对象上。
If the method was't implemented, you'll get an AttributeError (if it's not there at all) or a TypeError (if something by that name is there but it's not a function or it didn't have that signature). It's up to you how you handle that- either call it programmer error and let it crash the program (and it "should" be obvious to a python developer what causes that kind of error there- an unmet duck interface), or catch and handle those exceptions when you discover that your object didn't support what you wish it did. Catching AttributeError and TypeError is important in a lot of situations, actually.