美文网首页
python之abc和six

python之abc和six

作者: 俊杰的笔记 | 来源:发表于2017-04-18 09:55 被阅读4461次

abc是Abstract Base Classes的缩写
six的元类注解兼容python2和3

import abc

import six


@six.add_metaclass(abc.ABCMeta)
class PluginBase(object):
    @abc.abstractmethod
    def func_a(self, data):
        """
        an abstract method need to be implemented.
        :param data: 
        :return: 
        """

    @abc.abstractmethod
    def func_b(self, output, data):
        """
        another abstract method need to be implemented.
        :param output: 
        :param data: 
        :return: 
        """


class RegisteredImplementation(object):
    def func_c(self, data):
        print "Method in third-party class, " + str(data)

PluginBase和RegisteredImplementation在语法上没有任何继承关系。
但PluginBase的元类是abc.ABCMeta
PluginBase本身是由ABCMeta创建出来的。ABCMeta作为元类,其方法的第一个参数是cls, 代表元类的实例,即指定元类为ABCMeta的类,也就是PluginBase

在ABCMeta中有个register方法:

def register(cls, subclass):
    """Register a virtual subclass of an ABC."""
    # ...

PluginBase可以直接调用register,就像实例调用实例方法一样,点操作符前面是“接收者”: PluginBase.register(RegisteredImplementation)
等同于: abc.ABCMeta.register(PluginBase, RegisteredImplementation)

那么这个方法是干什么的?从源码可以看出,是将一个类注册为这个类的虚拟子类。
实验一下:

if __name__ == '__main__':
    # OOP=> PluginBase.register(RegisteredImplementation)
    abc.ABCMeta.register(PluginBase, RegisteredImplementation)

    for sc in PluginBase.__subclasses__():
        print "subclass of PluginBase: " + sc.__name__

    print "----------"
    print issubclass(RegisteredImplementation, PluginBase)
    print isinstance(RegisteredImplementation(), PluginBase)
    print "----------"

    obj1 = RegisteredImplementation()
    obj1.func_c("")

    # 报错,AttributeError: 'RegisteredImplementation' object has no attribute 'func_a'
    obj1.func_a("asdf")

首先将RegisteredImplementation注册为PluginBase的虚拟子类;
然后查看PluginBase的subclasses, 结果什么也没打出。说明虚拟子类不是真正的子类。
再查看issubclass和isinstance方法,均打印True. 说明虚拟子类影响这两个判断方法
最后尝试用RegisteredImplementation的实例调用自身和PluginBase的方法,结果调用自身的方法OK,调用PluginBase的抽象方法报错了。

虚拟子类就到这里。下面看下,如果一个类继承了PluginBase会怎样
PluginBase指定了元类,且声明了两个抽象方法。

class RealSubclass(PluginBase):
    def func_a(self, data):
        print "impl"

    def func_x(self):
        print "func_x"

if __name__ == '__main__':
    # TypeError: Can't instantiate abstract class RealSubclass with abstract methods func_b
    x = RealSubclass()

由此可见,PluginBase利用six和abc的注解充当了Java中interface的角色
继承PluginBase的类必须全部实现其抽象方法,否则实例化会报错。

简单总结:

  1. 用法:
  • @six.add_metaclass(abc.ABCMeta)用于指定元类,兼容python2和3
  • @abc.abstractmethod用于声明抽象方法;
  • abc.ABCMeta.register方法用于将任意类注册为虚拟子类
  1. 通过标准方式继承抽象类的类,必须全部实现抽象类的抽象方法,否则不能实例化
  2. 虚拟子类不影响subclasses, 可以不实现抽象方法,只要不调用。

相关文章

  • python之abc和six

    abc是Abstract Base Classes的缩写six的元类注解兼容python2和3 PluginBas...

  • [ZT] python之six用法

    python之six用法 前言 最近在写一个django的项目,在form的底层函数当中看见了six的使用,就来学...

  • 解决docker-compose的ImportError: ca

    这个问题源于python six安装错误或版本过期。 重装python six再使用pip重装docker-com...

  • python之six用法

    前言 最近在写一个django的项目,在form的底层函数当中看见了six的使用,就来学习一下。也希望写的这些东西...

  • Python的six模块相关

    import six 了之后 six.unichr(hexnum)其实等同于Python3中的chr(hexnum...

  • Python之abc模块

    abc:Abstract Base Classes 作用:在代码中定义和使用抽象基类进行API检查。 1. 为什么...

  • python基础(abc类)

    abc ABC是Abstract Base Class的缩写。Python本身不提供抽象类和接口机制,要想实现抽象...

  • 2018-06-01

    ##Missing Xcode dependency: Python module "six". Mac 配置fl...

  • Python six day

    文件复制1 大文件处理方式readline()读一行 输入是字符串readlines()一行一行的都去完 输出是列...

  • Python six模块

    在TensorFlow Object Detection API的范例程序:object_detection_tu...

网友评论

      本文标题:python之abc和six

      本文链接:https://www.haomeiwen.com/subject/pnffzttx.html