元类

元类

元类的介绍

元类就是用来实例化类的类,即元类的实例化为类,类的实例化为对象。

我们都知道对象是怎么产生的 ,

class People:
	def __init__(self,name,age):
		self.name = name
		self.age =age
		

# 类的实例化产生对象
p1 = People("tom",14)

print(type(People))  # <class "type">  说明People类是由type元类实例化的类。

类的实例化是通过调用类名()的方式实例化对象。那么元类是不是也是通过这种方式来实例化类呢?

通过打印type(People)可以看出People类是由type元类实例化的类。当类不注明其继承的元类时,一般都默认继承type元类。

如何自定义产生类

类一共有三大特征:类名、类的基类、执行类体代码的名称空间。通过这三个特征,我们 可以造出来一个类。

# 类的名字
class_name = "People"

# 类的基类
class_bases = (object)

# 执行类体代码拿到的名称空间
class_dic = {}
class_body = '''
	def __init__(self,name,age):
		self.name = name
		self.age = age
	
'''
exec(class_body,{},class_dic)

# 调用type元类,将三个参数传入,实例化产生类。
People= type(class_name,class_bases,class_dic)

exec(“字符串形式的代码”,{字典形式的全局作用域},{局部作用域})。当执行这一方法的时候,首先会执行字符串形式的代码,将在其内部产生的局部名称空间内部。

上述代码就实现了自定义类的创建,这就是class关键字执行的步骤。

如何自定义产生元类

通常情况下,创建类没有声明自己的元类,那么默认其元类为type。我们还可以自定义元类来创建类。这时,我们都是使用metclass关键字来自定义元类。当然,所有的元类都必须继承type,只有继承了type,才能被称为元类。

class Mymeta(type):   # 只有继承了type 才能被称为元类。
	pass
	
class People(object,metaclass=Mymeta):  # 一般情况默认metaclass = "type"
	def __init__(self,name,age):
		self.name = name
		self.age = age

之前我们说过,元类实例化产生类,那么我们实例化People类的过程实际就是调用Mymeta元类的过程,然后将class_name,class_bases,class_dic当作参数传入_init_。最后产生了类

  1. 在调用Mymeta元类的时候首先会产生一个类的空对象。
  2. 初始化对象。
  3. 返回初始化好的对象。

按照上述过程,可以总结为

  1. 首先执行了Mymeta元类的__new__方法,产生类的空对象。
  2. 其次执行了__init__方法初始化了类对象。
  3. return了一个初始化之后的类对象。
class Mymeta(type):
	def __init__(self,class_name,class_bases,class_dic):
		super().__init__(class_name,class_bases,class_dic)
	
	def __new__(cls,*args,**kwargs):
		return super().__new__(cls,*args,**kwargs)
    
People = Mymeta(class_name,class_bases,class_dic)
    
class People(object,metaclass=Mymeta):  # 一般情况默认metaclass = "type"
	def __init__(self,name,age):
		self.name = name
		self.age = age

因此,只要是调用类的时候,都会调用类的_new__和__init_。

为什么对象不能通过加括号的方式调用呢?因为对象内没有__call__的内置方法。既然元类可以加括号来调用,那么就说明其一定有一个__call__在被调用的时候就自动执行了,那么其返回值也就是该内置方法的返回值。

那么就是说调用__init____new__肯定是发生在__call__内部的。

posted @ 2020-04-15 16:53  小菜鸟是我  阅读(156)  评论(0编辑  收藏  举报