Python基类,使抽象方法在实例化时强制定义

3
我有一个基类,其中定义了几个空方法。我希望在子类中强制要求/使这些方法的定义成为必须,并在初始化时如果它们没有被重写就使程序崩溃。
例如:
class Shape:
    def __init__(self, name):
        self.name = name
    def number_of_edges(self):
        pass  # method HAS TO be overloaded in subclass

class Triangle(Shape):
    def __init__(self, name):
        super(Triangle, self).__init__()

    def number_of_edges(self):
        return 3

看起来,Python 的方式是引发一个 NotImplementedError

def number_of_edges(self):
    raise(NotImplementedError)

在类实例化期间崩溃并检测缺少的实现可能是有益的。为什么这不是默认设置,是否可以实现?

2个回答

3
使用abc模块创建一个抽象基类。
import abc

class Shape(object):
    __metaclass__ = abc.ABCMeta

    def __init__(self, name):
        self.name = name

    @abc.abstractmethod
    def number_of_edges(self):
        pass

任何使用@abc.abstractmethod装饰的方法都会触发TypeError异常:

>>> import abc
>>> class Shape(object):
...     __metaclass__ = abc.ABCMeta
...     def __init__(self, name):
...         self.name = name
...     @abc.abstractmethod
...     def number_of_edges(self):
...         pass
...
>>>  
>>> class Triangle(Shape):
...     pass
... 
>>> Triangle('t3')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Triangle with abstract methods number_of_edges
>>> class Triangle(Shape):
...     def number_of_edges(self):
...         return 3
... 
>>> Triangle('t3')
<__main__.Triangle object at 0x105f3b8d0>

在Shape中,__init__的作用是什么?如何实例化Shape中的name的值? - NightFurry
@NightFurry:你需要问原帖作者为什么他们的形状有一个name属性;__init__函数是用来在创建实例时从给定的参数中存储该属性的。 - Martijn Pieters
其实我不知道如何在元类中实例化类变量。只是想问一下这个问题。 - NightFurry

1
你可以使用抽象基类;
import abc
class Shape:
    __metaclass__ = abc.ABCMeta   

    def __init__(self, name):
        self.name = name

    @abc.abstractmethod
    def number_of_edges(self):
        pass  # method HAS TO be overloaded in subclass

现在,如果Triangle类没有覆盖number_of_edges方法,它将会引发异常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接