zoukankan      html  css  js  c++  java
  • 元类

    元类的定义
    
    实例化一个类,产生对象。
    在python中,类是怎么产生的?
    
    实例化一个元类,得到一个类。
    
    元类---实例化---->类(People)---实例化---->对象(obj)
    
    python强调一切皆对象。元类就是最初的类,它可以产生别的类,别的类在产生对象。
    
    调用类的__class__方法:得到元类type
    
    属性的查找顺序:
    属性查找:对象本身,类,父类,,,父类不是元类
    以对象为起始找,找不到元类里去,
    以类为起始找,能找的到元类
    
    元类实例化产生的就是类,class语法,就是对元类的实例化,产生一个类。
    类的三大特征:类名、类的基类、执行类体代码,拿到类的名称空间
    这是两种相同的意思:
    class People
    People = type(类名,类的基类,名称空间)
    People是对元类type的实例化。
    
    产生类的过程:
    实例化类发生的事:(类也是对象)
    
    产生一个空对象,调用__new__方法,返回空对象,和参数给__init__方法;
    有了空对象,调用type的__init__方法,初始化对象;
    返回对象
    
    所有的步骤,肯定会有一段代码来控制,这个方法是__call__,当对象被调用时执行
    
    当我们调用一个整数类型的时候,会报错,不可调用。
    当我们调用一个函数的的时候,它是可以调用的。
    
    所以,决定一个变量可不可以被调用,是看它是什么类型。
    所以,__call__方法,被定义在类里,当生成的对象被调用的时候,它就被触发了。
    对象是一个具体的,类是抽象的,包含各种属性,数据属性,方法属性,还有一些内置方法,比如,__call__,当满足一定条件的时候,就触发执行。
    
    len :__len__
    'abc':__str__ :打印时,触发   return 值,被打印
    __init__ :实例化对象时,触发
    __del__ :删除,清理对象时,触发,程序结束,也是这个情况,将对象清理了
    当程序调用了系统的资源,可以程序结束的时候,帮系统释放
    
    重点:
    首先,通常对象是不可以被调用的,为什么:因为对象所属的类中没有__call__方法,所以不可以被调用。
    而,产生对象,将类进行实例化,people = People('egon',20),这是调用类People,返回一个对象people。
    所以,类是可以被调用的,所以,类所属的类中,是有__call__方法的。
    
    即,元类中有__call__方法,普通的类是没有__call__方法的。(当然你也可以加,这样对象也可以被调用,我们讨论的是正常的情况)
    
    当,实例化类产生对象的时候,也就是 类 被调用了,这样就会触发 元类 中的__call__方法的执行。即,元类中的__call__方法执行
    
    当类被调用,也就是实例化类产生对象,元类中__call__方法执行,类在实例化产生对象的过程,这个过程,就是__call__方法执行的过程。
    即,产生空对象,初始化对象,返回对象。
    产生空对象是__new__方法,完成的;然后,在将空对象self,和参数,传入__init__方法将对象进行初始化;最后返回一个对象。
    
    __new__ :早于__init__执行,
    def __new__(cls,*args,**kwargs):
        cls :这个类本身
        args:元组:对象名,对象基类,对象名称空间(对象好像没有这些,,,毕竟是新产生的,然后,继承是类所具有的)
    
    自定义元类:Mymeta
    
    class People(metaclass=Mymeta):
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def say(self):
            print('%s:%s' %(self.name,self.name))
    
        def __new__(cls, *args, **kwargs):
            # 产生真正的对象,注意这个是object类的继承
            return object.__new__(cls)
    
    # 类的调用
    # obj=People('egon',18) =》Mymeta.__call__=》干了3件事
    # 1、Mymeta.__call__函数内会先调用People内的__new__
    # 2、Mymeta.__call__函数内会调用People内的__init__
    # 3、Mymeta.__call__函数内会返回一个初始化好的对象
    
    通常的类的定义中,没有__new__方法:
    <built-in method __new__ of type object at 0x000000001D8131C0>
    这是一个元类的内置方法,注意:类是元类的实例化。所以,类中没有,去元类找。
    raise NameError('...')  抛出异常(这只是个语法)
    
    自定义元类:元类是type,我们可以自定义一个元类,在原来的基础上,加一些功能或逻辑。Mymeta是一个自定义的元类。meta元类的意思。
    一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type,我们也可以通过继承type来自定义元类,然后使用metaclass关键字参数为一个类指定元类
    
    class Mymeta(type): # 只有继承了type类的类才是元类
        def __call__(self, *args, **kwargs):
            # 1、Mymeta.__call__函数内会先调用People内的__new__
            people_obj=self.__new__(self)
            # 2、Mymeta.__call__函数内会调用People内的__init__
            self.__init__(people_obj,*args, **kwargs)
    
            # print('people对象的属性:',people_obj.__dict__)
            people_obj.__dict__['xxxxx']=11111
            # 3、Mymeta.__call__函数内会返回一个初始化好的对象
            return people_obj
    
    产生类StanfordTeacher的过程就是在调用Mymeta,而Mymeta也是type类的一个对象,那么Mymeta之所以可以调用,一定是在元类type中有一个__call__方法
    # 类的产生
    # People=Mymeta()=》type.__call__=>干了3件事
    # 1、type.__call__函数内会先调用Mymeta内的__new__
    # 2、type.__call__函数内会调用Mymeta内的__init__
    # 3、type.__call__函数内会返回一个初始化好的对象
    
    
    补充:exec的用法
    
    #exec:三个参数
    
    #参数一:包含一系列python代码的字符串
    
    #参数二:全局作用域(字典形式),如果不指定,默认为globals()
    
    #参数三:局部作用域(字典形式),如果不指定,默认为locals()
    
    #可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中
    g={
        'x':1,
        'y':2
    }
    l={}
    
    exec('''
    global x,z
    x=100
    z=200
    
    m=300
    ''',g,l)
    
    print(g) #{'x': 100, 'y': 2,'z':200,......}
    print(l) #{'m': 300}
    
  • 相关阅读:
    【LOJ】#2888. 「APIO2015」巴邻旁之桥 Palembang Bridges
    【AtCoder】ARC099题解
    【LOJ】#2265. 「CTSC2017」最长上升子序列
    【LOJ】#2264. 「CTSC2017」吉夫特
    【AtCoder】AGC028 (A-E)题解
    【AtCoder】ARC100 题解
    【AtCoder】ARC101题解
    【AtCoder】AGC026 题解
    【LOJ】 #2308. 「APIO2017」商旅
    【BZOJ】3456: 城市规划(多项式求ln)
  • 原文地址:https://www.cnblogs.com/pythonwl/p/12707070.html
Copyright © 2011-2022 走看看