• 元类


    **自定义元类

    储备知识:

    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
  • 相关阅读:
    Navicat 导出sql问题
    2017,我的第一次年终总结
    dev treelist和searchcontrol组合模糊查询用法
    构造函数详解
    Devexpress常见问题
    Devexpress 常用的功能
    dev Gridcontrol控件属性部分
    记录DEV gridview获取行列数据方法
    string类的几种方法
    plsql中的procedure和function编程
  • 原文地址:https://www.cnblogs.com/xuechengeng/p/10045952.html
Copyright © 2020-2023  润新知