这是一个从Python 3.3的 abc 模块中的源代码派生的工作示例:
from abc import ABCmetaclass abstractclassmethod(classmethod): __isabstractmethod__ = True def __init__(self, callable): callable.__isabstractmethod__ = True super(abstractclassmethod, self).__init__(callable)class DemoABC: __metaclass__ = ABCmeta @abstractclassmethod def from_int(cls, n): return cls()class DemoConcrete(DemoABC): @classmethod def from_int(cls, n): return cls(2*n) def __init__(self, n): print 'Initializing with', n
运行时的外观如下:
>>> d = DemoConcrete(5) # Succeeds by calling a concrete __init__()Initializing with 5>>> d = DemoConcrete.from_int(5) # Succeeds by calling a concrete from_int()Initializing with 10>>> DemoABC() # Fails because from_int() is abstract Traceback (most recent call last): ...TypeError: Can't instantiate abstract class DemoABC with abstract methods from_int>>> DemoABC.from_int(5) # Fails because from_int() is not implementedTraceback (most recent call last): ...TypeError: Can't instantiate abstract class DemoABC with abstract methods from_int
请注意,最后一个示例失败,因为
cls()不会实例化。 ABCmeta 可以防止尚未定义所有必需抽象方法的类的过早实例化。
调用from_int() 抽象类方法时触发失败的另一种方法是使它引发异常:
class DemoABC: __metaclass__ = ABCmeta @abstractclassmethod def from_int(cls, n): raise NotImplementedError
设计 ABCmeta 会不遗余力防止在未实例化的类上调用任何抽象方法,因此您可以通过调用
cls()类方法(通常是这样做的)或引发
NotImplementedError 来触发失败。无论哪种方式,您都会遇到一个不错的干净故障。
可能很想编写一个描述符来拦截对抽象类方法的直接调用,但这与 ABCmeta的 总体设计是 矛盾的 ( ABCmeta的总体设计
是关于在实例化之前检查必需的方法,而不是在调用方法时)。 。



