Python标准库abc介绍

Python标准库abc介绍

前言

很多书都没有提到abc。python本身并没有抽象类,抽象函数。它是能过标准库abc提供的。
以前也热衷于造轮子,现在越来越趋向于去熟悉有哪些轮子,能不造则不造,这样开发起来效率快多了。
用于写代码的时候越少,用于思考的时间就越多。
之前看到的几本书,<python标准库>,<python绝技:运用python成为顶级黑客>,<Head+First+Python(中文版)>,,都没有看到abc库。
直到<python学习手册>里才看到。这本书我也是极力推荐阅读的。

最近看到的<Python高手之路>更是极力推荐abc库,说是大多数人居然不知道abc库的存在,还自己去造轮子。

抽象超类的使用方式

Python2.6和Python3.0的抽象超类
方法1:在需要由子类重载的方法中用assert或者raise NotImplementedError异常来指明子类必须重载。
方法2:特殊语法
在Python3.0中,我们在一个class头部使用一个关键字参数,以及特殊的@装饰器语法。

>>> from abc import ABCMeta,abstractmethod
>>> class Super(metaclass=ABCMeta):
...     @abstractmethod
...     def method(self):
...             pass
...
>>>

在Python2.6中,我们使用了一个类属性:

>>> from abc import ABCMeta,abstractmethod
>>> class Super:
...     __metaclass__ = ABCMeta
...     @abstractmethod
...     def method(self):
...             pass
...
>>>

当子类没有重载抽象方法时不能实例化的。

我感觉python中最应该掌握的概念是装饰器。
像上面的@abstractmethod就是用的装饰器语法。
还有@staticmethod和@classmethod 也都是依赖装饰器语法才提供的静态方法和类方法更便捷的使用方法。

ABCMeta更多的使用方式

使用ABCMeta作为metaclass的类有以下方法:
register(subclass)
把subclass注册为这个ABC的抽象子类。例如:

from abc import ABCMeta

class MyABC(metaclass=ABCMeta):
    pass
    
MyABC.register(tuple)

assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)

还有另一种方法把一个类变成一个ABC类的子类。
那就是重写这个ABC类的__subclasshook__(subclass)(这是个类方法)
通过这种方法可以把一个类只需要满足接口要求就自动成为这个ABC类的子类,而不需要调用register方法,又或者让该类继承自此ABC类。
此方法有3返回值:

  • True subclass 就是 这个ABC的子类。
  • False subclass不是这个ABC的子类。
  • NotImplemented. 继续按常规机制检查subclass是否是这个ABC的子类。
from abc import ABCMeta
import collections

class MyAbc(metaclass=ABCMeta):

    @classmethod
    def __subclasshook__(Class,Subclass):
        if Class is MyAbc:
            attributes = collections.ChainMap(*(Superclass.__dict__ for Superclass in Subclass.__mro__))
            methods = ("test","sayhello")
            if all(method in attributes and callable(method) for method in methods):
                return True
            else:
                return False
        return NotImplemented
class Test(MyAbc
    def saygoodbye(self):
        pass

assert(issubclass(Test, MyAbc))

有没有return False,assert结果不一样。
有return False, assert会失败。
没有return False,assert则成功。

Tags: