Python中对于元类的理解
类对象 实例化成为一个 实例对象,那么 类对象 如何 来的?
元类(metaclass)可以控制类的创建过程,它主要做三件事:
- 拦截类的创建
- 修改类的定义
- 返回修改后的类
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. 补充(元类制造了A类对象后,用__call__还可以控制A()的结果,就是实例对象的结果)
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)