zoukankan      html  css  js  c++  java
  • 元类

    元类

    元类的介绍

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

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

    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__内部的。

  • 相关阅读:
    scan design rules
    scan cell
    DFT basics
    测试性分析
    DFT设计绪论
    clock gate cell
    Linux命令
    Multi-voltage和power gating的实现
    Power Gating的设计(架构)
    Power Gating的设计(模块二)
  • 原文地址:https://www.cnblogs.com/liqianxin/p/12706439.html
Copyright © 2011-2022 走看看