8.12 定义接口或者抽象基类

    使用 模块可以很轻松的定义抽象基类:

    抽象类的一个特点是它不能直接被实例化,比如你想像下面这样做是不行的:

    1. a = IStream() # TypeError: Can't instantiate abstract class
    2. # IStream with abstract methods read, write

    抽象类的目的就是让别的类继承它并实现特定的抽象方法:

    1. def serialize(obj, stream):
    2. if not isinstance(stream, IStream):
    3. raise TypeError('Expected an IStream')
    4. pass

    除了继承这种方式外,还可以通过注册方式来让某个类实现抽象基类:

    还能注解静态方法、类方法和 。你只需保证这个注解紧靠在函数定义前即可:

    1. @property
    2. @abstractmethod
    3. def name(self):
    4. pass
    5.  
    6. @name.setter
    7. @abstractmethod
    8. def name(self, value):
    9. pass
    10. @classmethod
    11. @abstractmethod
    12. def method1(cls):
    13. pass
    14.  
    15. @staticmethod
    16. @abstractmethod
    17. def method2():
    18. pass

    标准库中有很多用到抽象基类的地方。collections 模块定义了很多跟容器和迭代器(序列、映射、集合等)有关的抽象基类。 库定义了跟数字对象(整数、浮点数、有理数等)有关的基类。io 库定义了很多跟I/O操作相关的基类。

    尽管ABCs可以让我们很方便的做类型检查,但是我们在代码中最好不要过多的使用它。因为Python的本质是一门动态编程语言,其目的就是给你更多灵活性,强制类型检查或让你代码变得更复杂,这样做无异于舍本求末。

    原文: