元类
什么叫元类
我们知道在python中一切皆对象(object),那么所以有的对象都成了object的子类,那么object类又是由谁创建的呢?
实际上,能够创建类的类,叫元类。还有一个概念就是:元类创建了object类,同时又是object类的子类(这是什么鬼?我们就不去考虑这个逻辑了,已经完美解决了先有鸡还是先有蛋的问题了)。
元类实际还是所有类的创建者,即使所有类(包括元类自己)都是object的子类,他们的关系如下:
Interesting......
class的底层
当我们使用class 类名
的时候,就会把类构造出来。实际上是元类实例化产生类,隐藏的语法如下:
type(name, bases, dict)
,传入三个参数时,代表class语句的动态形式,name
字符串即类名并且会成为__name__
属性;bases
元组列出基类并且会成为__bases__
属性;而dict
字典代表类的名称空间即__dict__
属性。
例如,以下两条语句会创建相同的type对象:
class A:
a = 1
A = type('A',(object,), dict(a = 1))
使用type控制类的产生
自定义元类:继承type:
class Mymeta(type):
def __init__(self, name, bases, dic):
'''控制类的产生,在__new__之后'''
#self 是A这个类(type的对象)
#在这个位置,其实self也就说A这个类,内部已经有东西了,名称空间已经有东西了
#所以在这个地方,可以通过dic来判断名称空间
#也可以直接通过self.__dict__/self.属性 来判断
a = self.__dict__.get('attr').get('name') # 后面做了修改
if not a:
raise Exception("没有name 属性")
super().__init()
def __new__(cls, name, bases, dic):
'''最根本上控制类产生,其实本质最根上也不是它,是type的__call__,但是我们控制不了了'''
dic2 = {'attr' : {}}
for k,v in dic.items():
if not k.startswith('__'):
dic2['attr'][k] = v
else:
dic2[k] = v
return type.__new__(cls, name, bases, dic2) # 必须返回
def __call__(self, *args, **kwargs):
'''控制类对象的产生'''
print(args,kwargs)
obj = self.__new__(self)
obj.__init__(*args, **kwargs)
return obj # 必须返回一个类的对象
class A(metaclass=Mymeta):
name = 'ddd'
def __init__(self, id):
self.id = id
def __repr__(self):
return 123
a = A(111)
元类里最重要的有三个魔术方法:
__init__
:控制类的产生,在__new__
之后__call__
:控制类对象的产生__new__
:最根本上控制类产生,其实本质最根上也不是它,是type的__call__
,但是我们控制不了了