zoukankan      html  css  js  c++  java
  • 元类

    **自定义元类

    储备知识:

    class Foo:
        def __call__(self, *args, **kwargs):
            print(self)
            print(args)
            print(kwargs)
    
    obj=Foo()
    #1、要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个方法__call__方法,该方法会在调用对象时自动触发
    #2、调用obj的返回值就是__call__方法的返回值
    res=obj(1,2,3,x=1,y=2)

    自定义元类:

    class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
        def __call__(self, *args, **kwargs): #self=<class '__main__.OldboyTeacher'>
            #1、调用__new__产生一个空对象obj
            obj=self.__new__(self) # 此处的self是类OldoyTeacher,必须传参,代表创建一个OldboyTeacher的对象obj
    
            #2、调用__init__初始化空对象obj
            self.__init__(obj,*args,**kwargs)
    
            #在初始化之后,obj.__dict__里就有值了
            obj.__dict__={'_%s__%s' %(self.__name__,k):v for k,v in obj.__dict__.items()}
            #3、返回初始化好的对象obj
            return obj
    
    class OldboyTeacher(object,metaclass=Mymeta):
        school='oldboy'
    
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def say(self):
            print('%s says welcome to the oldboy to learn Python' %self.name)
    
    t1=OldboyTeacher('egon',18)
    print(t1.__dict__) #{'_OldboyTeacher__name': 'egon', '_OldboyTeacher__age': 18}

      我们还是推荐在__call__中使用self.__new__(self)去创造空对象,因为这种方式会检索三个类OldboyTeacher->Foo->Bar,

    而object.__new__则是直接跨过了他们三个.

    class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
        n=444
        def __new__(cls, *args, **kwargs):
            obj=type.__new__(cls,*args,**kwargs) # 必须按照这种传值方式
            print(obj.__dict__)
            # return obj # 只有在返回值是type的对象时,才会触发下面的__init__
            return 123
    
        def __init__(self,class_name,class_bases,class_dic):
            print('run。。。')
    
    class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object),{...})
        n=111
    
        school='oldboy'
    
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def say(self):
            print('%s says welcome to the oldboy to learn Python' %self.name)
    
    print(type(Mymeta)) #<class 'type'>
    # 产生类OldboyTeacher的过程就是在调用Mymeta,而Mymeta也是type类的一个对象,那么Mymeta之所以可以调用,一定是在元类type中有一个__call__方法
    # 该方法中同样需要做至少三件事:
    # class type:
    #     def __call__(self, *args, **kwargs): #self=<class '__main__.Mymeta'>
    #         obj=self.__new__(self,*args,**kwargs) # 产生Mymeta的一个对象
    #         self.__init__(obj,*args,**kwargs) 
    #         return obj
  • 相关阅读:
    [bug] MySQL: The user specified as a definer ('root'@'%') does not exist
    [java] Maven安装本地jar包
    [bug] Openresty:content_by_lua_file 404
    [bug] Failed building wheel for xxx
    [bug] TypeError : unsupported operand type(s) for += : 'NoneType' and 'int'
    [Python] Flask从0到1开发轻量级网页
    [bug]Flask:KeyError: 'A secret key is required to use CSRF.'
    [bug] sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1054, "Unknown column 'recevie_name' in 'field list'")
    mac os 解决Error: EMFILE: too many open files错误
    从零开始的react入门教程(一),让我们从hello world开始
  • 原文地址:https://www.cnblogs.com/xuechengeng/p/10045952.html
Copyright © 2011-2022 走看看