• 回顾


    回顾

    一、sorted()和sort()的区别

    sorted():是内置函数,并不会修改原来的列表,可以针对字典等 迭代,有返回值

    sort():是绑定方法,会改变原有的列表,不能针对字典等迭代,没有返回值

    二、自定义字典

    自定义字典,使其具备点取值和点赋值功能

    class Mymeta(dict):
        def __setattr__(self, key, value):  #字典.get获取值会出现递归
            self[key] = value   #key = sex   #value = female
    
        def __getattr__(self, item):
            return self[item]  #就是获取键值对  name:yjy
    
    di = Mymeta(name = 'yjy',age = 20)
    print(di.name)    #点取值
    di.sex = 'female'  #点赋值
    print(di['sex'])
    

    三、自定义元类

    自定义元类,定义一个类,类的名称空间中必须有name字段才能成功,否则失败

    class Mymeta(type):
        def __init__(self,name,bases,dic):  #dic是类的属性和方法
                if 'name' not in dic:
                    raise Exception ('属性没有name字段')
    
    class Person(metaclass=Mymeta):
        name = 'oldboy'
        
    p = Person()  #oldboy
    print(p.name)
    

    自定义元类,定义一个类,继承字典,使其具备点取值和点赋值功能,通过元类控制的产生,把所有对象的属性放到attr字典中,属性全删除

    eg:di = Mydict(name = 'yjy',age = 18)

    di的名称空间中没有属性,只有attr字典,但是在attr字典中有其属性

    class Mymeta(type):
        def __call__(self, *args, **kwargs):
            obj = self.__new__(self)
            obj.__init__(*args, **kwargs)
            attr = kwargs
            obj.__dict__.clear()
            obj.__dict__['attr'] = attr
            return obj
    
    class Mydict(dict,object,metaclass=Mymeta):
        def __init__(self,**kwargs):
            self.__dict__.update(kwargs)
        def __getattr__(self, item):
            return self.__dict__['attr'][item]
        def __setattr__(self, key, value):
            self.__dict__['attr'][key] = value
    
    di = Mydict(name = 'qqq',age = 18)
    print(di.name)
    di.sex= 'male'
    print(di.sex)
    

    在元类中控制把自定义类的数据属性都变成大写

    class Mymeta(type):
        def __new__(cls, name,bases,dic):
            for k,v in dic.items():
                if not k.startswith('__'):
                    print(k.upper())
    class Person(metaclass=Mymeta):
        school='oldboy'
        age=10
    

    在元类中控制自定义类,无需__init__方法

    class Mymeta(type):
            def __call__(self, name,age):
                obj = object.__new__(self)
                obj.name = name
                obj.age = age
                return obj
    class Person(metaclass=Mymeta):
        school='oldboy'
        age=10
    
    p = Person('yjy',18)
    print(p.__dict__)
    

    在元类中控制把自定义类的数据属性都放在attr中

    class Mymeta(type):
        def __new__(cls, name,bases,dic):
            dic2={'attr':{}}
            for k,v in dic.items():
                if not k.startswith('__'):
                    dic2['attr'][k]=v
            return type.__new__(cls,name,bases,dic2)
    class Person(metaclass=Mymeta):
        school='oldboy'
        age=10
    print(Person.attr['school'])
    
    #自定义元类:继承type
    class Mymeta(type):
        def __init__(self,name,bases,dic):
            #self 是Person 这个类(对象)
            #在这个位置,其实self也就说Person这个类,内部已经有东西了,名称空间已经有东西了
            #所以在这个地方,可以通过dic来判断名称空间
            #也可以直接通过self.__dict__/self.属性 来判断
            a=dic.get('name')
            if not a :
                raise Exception('没有name属性,不能创建')
    
    class Person(metaclass=Mymeta):  #Person=Mymeta('Person',(object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__方法中
    # class Person():  #Person=Mymeta('Person',(object,),{...}) Mymeta类实例化,会把三个参数传到Mymeta的__init__方法中
        def __init__(self,name):
            self.name=name
            raise Exception('就不让你创建')
    
    p=Person('yjy')  #自动触发Person类__init__的执行
    #总结:可以通过自定义元类,重写__init__方法来控制类的产生
    
    
    
    
    #通过元类控制类的调用过程,实例化产生对象的过程
    class Mymeta(type):
        def __call__(self, *args, **kwargs):
            #该方法必须返回一个对象(类对象),这个地方返回什么 p=Person('lqz') p就是什么
            #返回一个真正的Person类的对象
            #第一步:产生一个空对象
            #object.__new__(self)  传一个参数,传类,就会产生一个该类的空对象
            #obj是Person类的空对象
            obj=object.__new__(self)
            # print(self.__new__ is object.__new__)  # True
    
            #第二步:初始化该对象,把初始值放到对象中
            #obj是Person类的空对象  obj.__init__  调用自己的绑定方法,也就说Person类中写的__init__方法
            obj.__init__(*args, **kwargs)
            #还可以类来调用
            # Person.__init__(obj,*args, **kwargs)
            # self.__init__(obj,*args, **kwargs)
            # print(obj.name)
            #第三步:把该对象返回
            return obj
    
    class Person(metaclass=Mymeta):
    # class Person():
        def __init__(self,name):
            self.name=name
        def __call__(self, *args, **kwargs):
            print('xxx')
    
    
    p=Person('lqz')
    print(p.name)
    print(p)
    # 原来的理解Person('lqz') 会调用Person类的__init__的方法
    # 这个位置会调用元类的__call__方法,所以在__call__方法中调用了Person  __init__方法,来完成对象的初始化
    p()
    
    
    #模板:控制对象的产生
    class Mymeta(type):
        def __call__(self, *args, **kwargs):
            obj=object.__new__(self)
            obj.__init__(*args, **kwargs)
            return obj
    
    class Person(metaclass=Mymeta):
        def __init__(self,name):
            self.name=name
        def __call__(self, *args, **kwargs):
            print('xxx')
    
    p=Person('lqz')
    
    #不用init方法,但是能完成对象的初始化
    class Mymeta(type):
        def __call__(self, name,age):
            # print(name)
            # print(age)
            obj=object.__new__(self)
            # obj.__init__(name,age)
            # obj.name=name
            # obj.age=age
            obj.__dict__['attr']={'name':name,'age':age}
            return obj
    
    class Person(metaclass=Mymeta):
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
    p=Person('lqz',18)
    print(p.__dict__)
    print(p.attr['name'])
    

    元类高阶

    __new__和__init__的区别
    __new__ 创建空对象
    __init__ 初始化空对象
    
    ------------------------------------------------------------------------------------
    class Person():
        def __init__(self,name,age):
            print('__init__')
            self.name=name
            self.age=age
        def __new__(cls, *args, **kwargs):
            print('__new__')
            #生成一个Person类的空对象
            return object.__new__(cls)
    
    p=Person('lqz',19)
    print(p)
    
    object.__new__ 传哪个类就得到哪个类的空对象
    p=object.__new__(Person)
    print(p)
    
    
    object.__new__(Person)    :生成Person类的对象  空的
    type.__new__(cls,name,bases,dic)  :生了cls这个类对象,里面有东西
    元类中
    __init__:控制类的产生,在__new__之后
    __call__:对着对象的产生
    __new__:控制类产生最根上,其实本质最根上也不是它,是type的__call__,但是我们控制不了了
    ---------------------------------------------------------------------------------
    class Mymeta(type):
        def __init__(self,name,bases,dic):
            #self 是Person类,Person类中有名称空间之类的了
            pass
        def __new__(cls, name,bases,dic):
     
            #产生空对象(空类),在这里面生成的并不是空类,是有数据的类了
            #如何完成类的初始化,并且把name,bases,dic这些东西放入
            # return type.__new__(cls,name,bases,dic)
            dic2={'attr':{}}
            for k,v in dic.items():
                #加入这一句,类名称空间中带__的就不会放到attr中
                if not k.startswith('__'):
                    dic2['attr'][k]=v
            print('-------',dic2)
            return type.__new__(cls,name,bases,dic2)
    
    
    class Person(metaclass=Mymeta):     # Person=Mymeta(name,bases,dic)   调用type的__call__,内部调用了Mymeta.__new__,又掉Mymeta的__init__
        school='oldboy'
        age=10
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
    print(Person.__dict__)
    print(Person.attr['school'])
    

    类的层级关系

  • 相关阅读:
    c# ThreadPool 判断子线程全部执行完毕的四种方法
    很多人都爱玩的lol..
    Go 的位操作
    wrk压测工具
    Go函数作为值与类型
    家用PC发展设想
    开车的烦恼
    一款一体机的设想
    nodejs开发环境的搭建
    Python网页抓取程序(续)
  • 原文地址:https://www.cnblogs.com/yanjiayi098-001/p/11461653.html
Copyright © 2020-2023  润新知