abc中的元类和six模块配合使用

metaclass是类的类或者元类,秉承Python一切皆对象的理念,Python中的类也是一类对象,metaclass的实例就是类(class),自己写metaclass时需要让其继承自type对象。关于metaclass的介绍,可以看python学习手册中的元类概念部分。
ABC(抽象基类),主要定义了基本类和最基本的抽象方法,可以为子类定义共有的API,不需要具体实现。abc模块,Python对于ABC的支持模块,定义了一个特殊的metaclass-ABCMeta 还有一些装饰器— @abstractmethod@abstarctpropertyabc.ABCMeta 是一个metaclass,用于在Python程序中创建抽象基类。

抽象基类可以不实现具体的方法(也可以实现),可以留给子类去实现。这类方法在抽象基类中是通过 @abstractmethod去实现的。抽象基类可以被子类直接继承,也可以将其他的类”注册“(register)到其门下当虚拟子类,虚拟子类的好处是你实现的第三方子类不需要直接继承自基类但是仍然可以声称自己子类中的方法实现了基类规定的接口issubclass(), issubinstance()!虚拟子类是通过调用metaclassabc.ABCMeta 的抽象基类的 register方法注册到抽象基类门下的,可以实现抽象基类中的部分API接口,也可以根本不实现,但是issubclass(), issubinstance()进行判断时仍然返回真值。

直接继承抽象基类的子类就没有这么灵活,在metaclassabc.ABCMeta的抽象基类中可以声明”抽象方法“和“抽象属性”,直接继承自抽象基类的子类虽然判断issubclass()时为真,但只有完全覆写(实现)了抽象基类中的“抽象”内容后,才能被实例化,而通过注册的虚拟子类则不受此影响。

metaclassabc.ABCMeta 的抽象基类如果想要声明“抽象方法”,可以使用abc模块中的装饰器 @abstractmethod,如果想声明“抽象属性”,可以使用abc模块中的@abstractproperty 。最后,为什么要提six模块呢,six模块是Python为了兼容Python 2.xPython 3.x提供的一个模块,该模块中有一个针对类的装饰器@six.add_metaclass(MetaClass)可以为两个版本的Python类方便地添加metaclass。这样我们就可以同时利用Python中的abc模块和six模块在类的定义前添加@six.add_metaclass(abc.ABCMeta)来优雅地声明一个抽象基础类了!

python2.xpython3.x下都可以通过下面的代码来实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from abc import ABCMeta, abstractmethod
import six

@six.add_metaclass(ABCMeta)
class MyClass1(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z

def add():
return self.x + self.y + self.z

@abstractmethod
def run(self):
"子类中实现该方法"

1
2
3
4
5
6
7
8
9
10
11
12
class metaTest(six.with_metaclass(ABCMeta, object)):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z

@abstractmethod
def run(self):
"""需要实现这个类的方法"""

def __len__(self):
return 3

而原始在python2python3中需要使用不同的方式:

1
2
3
4
5
6
7
8
# python2
class MyClass(object):
__metaclass__ = ABCMeta
pass

# python3
class MyClass3(object, metaclass=ABCMeta):
pass