这里自己整理了一下python的metaclass 在python中,所有都是对象,基本类型变量是,数据类型(int, float…)也是,就算是class也是对象 普通意义上的class,定义了该class实例的属性和方法, 而metaclass(即class的类),它定义了它的实例(class)以及它实例的实例(class的实例)的属性和方法

python默认的metaclass是type

首先介绍使用type来生成类

class = type(name, bases, dict)
# name: 类名, bases: 继承的基类, dict:属性

>>> def echoAge(self):
...   return self.age
...
>>> A = type('A', (object, ), {'age': 10, 'echoAge': echoAge})
>>> a = A()
>>> a.echoAge()
10
>>> a.age
10

现在真正以类的方式来实现metaclass

>>> class Meta(type):
...     def __new__(metacls, name, bases, dct):
...             print("enter __new__: ", metacls, name, bases, dct)
...             return super(Meta, metacls).__new__(metacls, name, bases, dct)
...     def __init__(cls, name, bases, dct):
...             print("enter __init__: ", cls, name, bases, dct)
...             super(Meta, cls).__init__(name, bases, dct)
...     def __call__(cls, *args, **kwargs):
...             print('enter __call__: ', cls, *args, **kwargs)
...             return super(Meta, cls).__call__(*args, **kwargs)
...
>>>
>>> class A(object, metaclass=Meta):
...     def echoAge(self):
...             return 10
...     age = 10
...
enter __new__:  <class '__main__.Meta'> A (<class 'object'>,) {'__qualname__': 'A', '__module__': '__main__', 'echoAge': <function A.echoAge at 0x1071f6a60>, 'age': 10}
enter __init__:  <class '__main__.A'> A (<class 'object'>,) {'__qualname__': 'A', '__module__': '__main__', 'echoAge': <function A.echoAge at 0x1071f6a60>, 'age': 10}
>>>
>>> a = A()
enter __call__:  <class '__main__.A'>

Meta.new__在生成A的对象时被调用,在调用return super(Meta, metacls).__new(metacls, name, bases, dct)前,可对A做修改, 如增加/修改A的属性或方法 Meta.__init__在生成A对象后进行初始化时被调用, 可直接对生成的对象A做修改,如增加/修改A的属性或方法 Meta.__call__在A(作为类)实例化时被调用(用metaclass来实现单例模式时就是在这里做文章)

实现将类的方法名,属性都改成大写的

>>> class Meta(type):
    def __new__(metacls, name, bases, dct):
        mydct = {}
        for k, v in dct.items():
            mydct.update({k.upper(): v})
        return super(Meta, metacls).__new__(metacls, name, bases, mydct)

>>> class A(object, metaclass=Meta):
    def lower(self):
        return 'lower'
    lowercase = 'lowercase'
    
>>> a = A()
>>> a.LOWER()
'lower'
>>> a.LOWERCASE
'lowercase'
>>> 

或者改写__init__方法来实现加一些方法

def upper(self):
    return 'upper'

class Meta(type):
    def __init__(cls, name, bases, dct):
        super(Meta, cls).__init__(name, bases, dct)    
        cls.upper = upper

class A(object, metaclass=Meta):
    def lower(self):
        return 'lower'

a = A()
a.upper()  ;'upper'
a.lower()  ;'lower'

改写__call__方法实现单例[类实例化时会调用__call__]

class Singleton(type):
    instance = None
    def __call__(cls, *args, **kwargs):
        if not cls.instance:
            cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls.instance

class Test(object, metaclass=Singleton):
    pass

a = Test()
b = Test()
print(id(a) == id(b))  #True

参考: http://eli.thegreenplace.net/2011/08/14/python-metaclasses-by-example