跬步 On Coding

Python 中的元类

参考

深刻理解Python中的元类(metaclass)

类与类的创建

Python中的class也是object,所以类可以作为参数,作为函数返回值,作为对象获取属性。

class MyClass(object):
    pass

myObject = MyClass()

type(myObject) # 获取对象的类
# <class '__main__.MyClass'>

type(MyClass) # 所有的类都是type类的对象
# <type 'type'>

myObject.__class__ # 获取对象的类
# <class '__main__.MyClass'>

MyClass.__class__
# <type 'type'>

类的定义,当我们用class关键字定义类的时候,Python是怎么生成类这个对象呢?

MyClass = type('MyClass', (), {}) # 类是用type函数创建的,所以类是type的对象
# type函数接受3个参数,类名称,类的父类元组(可以有多个父类),属性字典(方法是一个函数对象)

Python解释器看到关键字class就会用type工厂函数创建一个类。

metaclass

元类是用来创建类的类。

class ExClass(object):
    __metaclass__ = MyMetaClass

    pass

如果类属性中定义了__metaclass__,则在创建类的时候用元类来创建,如果没有则向其父类查找__metaclass__直到都没有,则用type()创建类。

class MyMetaClass(type): # type实际上也是类,所以可以被继承
    # __new__方法是一个特殊的方法用来创建并返回对象
    # __init__方法只是用来给对象传入初始化参数
    # 如果需要对类进行改写,则需要改写__new__方法
    def __new__(cls, name, bases, attrs)
        new_attrs = dosomething(attrs)
        return super(MyMetaClass, cls).__new__(cls, name, bases, new_attr)

super(MyMetaClass, cls).__new__()相当于type.__new__()MyMetaClasstype的子类。

元类做了什么事情呢?

  1. 拦截类的创建
  2. 修改类
  3. 返回修改后的类

metaclass一般是用不到的,但是有一个典型的使用场景ORM(对象关系映射),创建类的时候只有类属性,需要对类属性进行映射。