• day24-1 元类


    元类

    在python中一切皆对象,name我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类,即元类可以简称为类的类

    元类是负责产生类的,所以我们学习元类或者定义元类的目的是:为了控制类的产生过程,还可以控制对象的产生过程

    类的组成

    class People(object):
        x = 1
        print('from people')
        def __init__(self, name, age):
            self.name = name
            self.age = age
            
        def speak(self):
            print('from speak')
    

    在用class关键字定义类时,在定义阶段会执行类体中的代码,创建名称空间,所以类由三部分组成

    • 类名class_name:People
    • 基类class_bases:(object,)
    • 类的名称空间class_dic

    内置函数 exec()

    将字符串中的代码执行,然后把产生的全局名称丢入到global_space字典中,局部名称丢入到local_space字典中

    cmd = """
    x = 1
    global y
    y = 10
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def speak(self):
        print('from speak')
    """ 
    global_space = {}
    local_space = {}
    exec(cmd,global_space,local_space)  # 未声明gloabal的变量全是局部变量
    print('local:',local_space)
    
    local: {'x': 1, '__init__': <function __init__ at 0x000002C2319EB158>, 'speak': <function speak at 0x000002C2319EB0D0>}
    

    class关键字创建类原理

    用class关键字创建一个类,用的默认的元类type

    class_name = 'P'  # 类名
    class_bases = (object,)  # 基类
    cmd = """
    x = 1
    global y
    y = 10
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def speak(self):
        print('from speak')
    """ 
    global_space = {}
    local_space = {}
    exec(cmd,global_space,local_space)
    class_dic = local_space  # 类的名称空间
    
    P= type(class_name, class_bases, class_dic)
    print(P)
    
    <class '__main__.P'>
    

    自定义元类控制类的创建

    • 控制创建类时必须写说明,没写就抛出异常
    class Mymeta(type):
        def __init__(self, class_name, class_bases, class_dict):
            if not class_dict.get('__doc__'):
                raise TypeError('必须写说明')
            super(Mymeta, self).__init__(class_name, class_bases, class_dict)
    
    
    class People(object, metaclass=Mymeta):
        """
        SJFDSFSD
        """
        country = 'Chinese'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def test(self):
            print('from f1')
    
    • 控制创建类时类名不能全为小写,类名全为小写则抛出异常
    class Mymeta(type):
        def __init__(self, class_name, class_bases, class_dict):
            if class_name.islower():
                raise TypeError('类名不能全为小写')
            super(Mymeta, self).__init__(class_name, class_bases, class_dict)
    
    
    class People(object, metaclass=Mymeta):
        country = 'Chinese'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def test(self):
            print('from f1')
    

    自定义元类控制类实例化

    类的实例化就是元类的调用,类实例化原理:

    • 先造出一个空对象
    • 为该空对象初始化独有的属性
    • 返回一个初始化好的对象
    class Mymeta(type):
        def __init__(self, class_name, class_bases, class_dict):
            super(Mymeta, self).__init__(class_name, class_bases, class_dict)
    
        # 控制类Foo的调用过程,即控制实例化Foo的过程
        def __call__(self, *args, **kwargs):
    
            # 造一个空对象obj
            obj = object.__new__(self)
    
            # 调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__
            self.__init__(obj, *args, **kwargs)
            return obj
    
    
    class Foo(object, metaclass=Mymeta):
        x = 10
    
        def __init__(self, y):
            self.y = y
    
    
    f = Foo(1)
    print(f.__dict__)
    
    {'y': 1}
    

    自定义元类后对象属性查找顺序

    对象本身-->类-->父类-->父类-->object-->type找不到报错

  • 相关阅读:
    JadConfig 注解驱动的java 配置管理包
    coroot 开源微服务架构监控以及问题解决工具
    observIQ 开源的OpenTelemetry collector 实现
    graylog MessageOutput 简单说明
    graylog 的schema
    【职场】辞职的时间节点有讲究,你知道吗?
    【精选】面试官:聊下常见设计模式有哪些?
    今日头条架构千字分析,这一篇就够了
    【收藏分享】2022年PHP中高级面试题(三)
    四种策略确保 RabbitMQ 消息发送可靠性
  • 原文地址:https://www.cnblogs.com/863652104kai/p/11083661.html
Copyright © 2020-2023  润新知