Python中对于元类的理解

元类(metaclass)可以控制类的创建过程,它主要做三件事: 1.拦截类的创建 2.修改类的定义 3.返回修改后的类

1.元类是制造类的工厂

# type是一个特殊的元类
Hello = type("Hello", (object,), {"say_hello": lambda self, value: print("hello {}".format(value))})

if __name__ == "__main__":
    print(Hello)
    h = Hello()
    h.say_hello("world")

"""
输出:
<class '__main__.Hello'>
hello world
"""

2.自定义元类

class NewMetaClass(type):
    def __new__(cls, name, bases, attrs): # name是你要制造成类的名字(类A),bases是类A的父类,attrs是一个字典,放有类A里的属性和方法
        print(cls)  # 此刻cls是NewMetaClass元类对象
        print(super(NewMetaClass, cls).__new__(cls, name, bases, attrs))  # (super...) 是A的类对象
        return super(NewMetaClass, cls).__new__(cls, name, bases, attrs)  # return xxx 以后传入self

    def __init__(self, *args, **kwargs):
        # 此self是A的类对象 (另super(NewMetaClass, self).__init__(*args, **kwargs)的值为None)
        super(NewMetaClass, self).__init__(*args, **kwargs)
        print(self)


class A(object, metaclass=NewMetaClass):
    pass


if __name__ == "__main__":
    a = A()

"""
输出:
<class '__main__.NewMetaClass'>
<class '__main__.A'>
<class '__main__.A'>
"""

3.补充

class NewMetaClass(type):
    def __new__(cls, name, bases, attrs):
        print(cls)  # 此刻cls是NewMetaClass元类对象
        print(super(NewMetaClass, cls).__new__(cls, name, bases, attrs))  # (super...) 是A的类对象
        return super(NewMetaClass, cls).__new__(cls, name, bases, attrs)  # return xxx 以后传入self

    def __init__(self, *args, **kwargs):
        # 此self是A的类对象 (另super(NewMetaClass, self).__init__(*args, **kwargs)的值为None)
        super(NewMetaClass, self).__init__(*args, **kwargs)
        print(self)

    def __call__(self, *args, **kwargs):
        # 此self 是A的类对象, (super(NewMetaClass, self).__call__(*args, **kwargs))是A的类对象实例化后的 实例对象
        print(super(NewMetaClass, self).__call__(*args, **kwargs))
        return super(NewMetaClass, self).__call__(*args, **kwargs)


class A(object, metaclass=NewMetaClass):
    pass


if __name__ == "__main__":
    a = A()

"""
输出:
<class '__main__.NewMetaClass'>
<class '__main__.A'>
<class '__main__.A'>
<__main__.A object at 0x002EA350>
"""
# 此解释为,元类制造了A类对象后,用__call__还可以控制A()的结果,就是实例对象的结果

4.用元类方式写单例模式

class NewMetaClass(type):
    instance = None  # 定义一个空对象

    def __call__(self, *args, **kwargs):  # self为制造出的类对象(此处为A对象),这个函数__call__是再实例化类对象,结果也就是实例对象 
        if not hasattr(self, "instance"):
            self.instance = super(NewMetaClass, self).__call__(*args, **kwargs)
            return self.instance


class A(object, metaclass=NewMetaClass):
    pass


if __name__ == "__main__":
    a = A()
    b = A()
    c = A()
    print(id(a))
    print(id(b))
    print(id(c))

"""
输出:
1723436688
1723436688
1723436688
"""

5.用元类动态制造类MyList

class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return super(ListMetaclass, cls).__new__(cls, name, bases, attrs)

class MyList(list, metaclass=ListMetaclass):
    pass

if __name__ == "__main__":
    a = MyList()
    a.add("111")
    print(a)