zoukankan      html  css  js  c++  java
  • 元类

    一、eval内置函数:eval() 函数用来执行一个字符串表达式,并返回表达式的值。

    1. 语法:
      eval(expression[, globals[, locals]])
    dic_str = "{'a': 1, 'b': 2, 'c': 3}"
    print(eval(dic_str))
    
    list_str = "[1, 2, 3, 4, 5]"
    print(eval(list_str))
    
    tuple_str = "(1, 2, 3, 4, 5)"
    print(eval(tuple_str))
    
    # {'a': 1, 'b': 2, 'c': 3}
    # [1, 2, 3, 4, 5]
    # (1, 2, 3, 4, 5)
    

    二、exec内置函数:exec 执行储存在字符串或文件中的 Python 语句,相比于 eval,exec可以执行更复杂的 Python 代码。

       1.语法:

          exec(object[, globals[, locals]])
      2.返回值:
          exec 返回值永远为 None。

    # exec应用场景
    # 1.执行字符串没有执行结果(没有返回值)
    # 2.将执行的字符串中产生的名字形成对应的局部名称空间
    
    source = '''
    name = 'Bob'
    age = 20
    '''
    class A:
        pass
    a = A()
    
    dic = {}
    exec(source, {}, dic)
    a.__dict__ = dic
    print(a.__dict__)
    print(a.name)
    print(a.age)
    

      三、type类:面向对象编程,讲究的是万物皆对象,我们知道对象是由类实例化产生的,那么同理我们也可以把类看做一个对象,它是由元类type实例化产生的类。

            所有自定义类都是由type类实例化产生的,type类似元类,type类是由type类本身实例化产生的

    # 类是type的对象,可以通过type(参数)来创建类
    
    # type(name, bases, namespace)
    
    s = '''
    my_a = 10
    my_b = 20
    def __init__(self):
        pass
    @classmethod
    def print_msg(cls, msg):
        print(msg)
    '''
    namespace = {}
    exec(s, {}, namespace)
    
    Student = type('Student', (object, ), namespace)
    
    stu = Student()
    print(stu.__dict__) # {}
    print(stu.my_a)  # 10
    print(stu.my_b)  # 20
    

      

    # -*- coding: utf-8 -*-
    # 什么是元类
    #     源自于一句话:python 中一切皆对象,而对象是由类实例化得到的
    # class 关键字在定义类的时候,在python 3 中默认继承 object
    
    
    class Teacher(object):
        school = 'JSUN'
        
        def __init__(self, name, age):
            self.name = name
            self.age = age
        
        def score(self):
            print('%s is scoring' % self.name)
    
    
    tea1 = Teacher('QZK', 18)
    print(tea1.__dict__)  # {'name': 'QZK', 'age': 18}
    print(type(tea1))  # <class '__main__.Teacher'>
    print(type(Teacher))  # <class 'type'>
    print(Teacher.__dict__)
    print(id(Teacher))  # 4136376
    # {'__module__': '__main__', 'school': 'JSUN', '__init__': <function Teacher.__init__ at 0x00000000028F89D8>,
    # 'score': <function Teacher.score at 0x00000000028F88C8>, '__dict__': <attribute '__dict__' of 'Teacher' objects>,
    # '__weakref__': <attribute '__weakref__' of 'Teacher' objects>, '__doc__': None}
    
    
    """
    调用元类----->产生自定义类
    调用自定义类------->产生自定义的对象
    """
    
    """
    class 关键字底层工作原理,分为四部:
        1.先拿到类名
        2.再拿到类的基类们(元组形式)
        3.然后拿到类的名称空间(执行类体代码,然后将产生的名字放到类的名称空间,也就是字典里,exec())
        4.调用元类 实例化得到 自定义类
    
    
    自定义类的三个重要组成部分:
        1.类名
        2.类的基类们
        3.类的名称空间
    """
    
    """不依赖class 关键字创建一个自定义类"""
    # 1.拿到类名
    class_name = 'Student'
    # 2.拿到类的基类们
    class_base = (object,)
    # 3.拿到类的名称空间
    class_dic = {}
    class_body = """
    school = 'JSUN'
    
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def score(self):
        print('%s is scoring' % self.name)
    
    
    """
    exec(class_body, {}, class_dic)
    print(class_dic)
    # {'__module__': '__main__', 'school': 'JSUN', '__init__': <function Teacher.__init__ at 0x00000000022089D8>,
    # 'score': <function Teacher.score at 0x00000000022088C8>, '__dict__': <attribute '__dict__' of 'Teacher' objects>,
    # '__weakref__': <attribute '__weakref__' of 'Teacher' objects>, '__doc__': None}
    
    # 4.调用type得到自定义类
    Student = type(class_name, class_base, class_dic)
    st1 = Student('qzk', 18)
    print(Student.__dict__)
    # {'school': 'JSUN', '__init__': <function __init__ at 0x0000000001D31E18>,
    # 'score': <function score at 0x0000000002208AE8>, '__module__': '__main__', '__
    # dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>,
    # '__doc__': None}
    print(st1.__dict__)  # {'name': 'qzk', 'age': 18}
    print(st1.name)  # qzk
    
    
    
    
    # 自定义元类控制类的产生:
    # 1.类名必须为驼峰体
    # 2.类体中必须有文档注释
    
    
    class Mymeta(type):  # 但凡继承了type的类才能称之为自定义的元类,否则就是一个普通的类
        def __init__(self, class_name, class_bases, class_dic):
            if class_name.islower():
                raise TypeError('类名必须是驼峰体')
            doc = class_dic.get('__doc__')
            if doc is None or len(doc) == 0 or len(doc.strip('
     ')):
                raise TypeError('类体中必须由文档注释')
    
    
    class teacher(object, metaclass=Mymeta):
        #     raise TypeError('类名必须是驼峰体')
        # TypeError: 类名必须是驼峰体
        school = 'JSUN'
        
        def __init__(self, name, age):
            self.name = name
            self.age = age
        
        def score(self):
            print('%s is scoring' % self.name)
    
    #     raise TypeError('类体中必须由文档注释')
    # TypeError: 类体中必须由文档注释

    自定义类控制类的调用过程(在类调用过程中加以限制--(单例就是一种自定义类控制调用的方式)):

    # -*- coding: utf-8 -*-
    
    
    class Mymeta(type):  # 但凡继承了type的类才能称之为自定义的元类,否则就是一个普通的类
        pass
    
    
    class Teacher(object, metaclass=Mymeta):
        #     raise TypeError('类名必须是驼峰体')---》class teacher时触发
        # TypeError: 类名必须是驼峰体
        school = 'JSUN'
        
        def __init__(self, name, age):
            self.name = name
            self.age = age
        
        def score(self):
            print('%s is scoring' % self.name)
    
    
    tea = Teacher('QZK', 18)
    
    
    # tea()  # TypeError: 'Teacher' object is not callable
    
    
    class Mymeta(type):  # 但凡继承了type的类才能称之为自定义的元类,否则就是一个普通的类
        pass
    
    
    class Teacher(object, metaclass=Mymeta):
        #     raise TypeError('类名必须是驼峰体')---》class teacher时触发
        # TypeError: 类名必须是驼峰体
        school = 'JSUN'
        
        def __init__(self, name, age):
            self.name = name
            self.age = age
        
        def score(self):
            print('%s is scoring' % self.name)
        
        def __call__(self, *args, **kwargs):
            print(self)
            print(args)  # (1, 2, 3)
            print(kwargs)  # {'b': 1, 'c': 2}
    
    
    tea1 = Teacher('QZK', 18)
    tea1(1, 2, 3, b=1, c=2)
    
    
    # 总结:对象之所以可以被调用,是因为对象的类中有一个__call__ 函数
    # 推导:如果一切接对象,那么Teacher 类也是一个对象,该对象之所以可以被调用,肯定是这个对象的类中也定义了一个__call__函数
    # 实例化过程:
    #     1.产生一个空对象
    #     2.执行__init__完成对对象属性的初始化操作
    #     3.返回初始化好的那个对象
    
    class Mymeta(type):  # 但凡继承了type的类才能称之为自定义的元类,否则就是一个普通的类
        def __call__(self, *args, **kwargs):
            # 1.先产生一个空对象
            tea_obj = self.__new__(self)  # obj 是Teacher 类的对象
            # 2.执行__init__ 完成对对象的属性的初始化操作
            self.__init__(tea_obj, *args, **kwargs)
            # 3.返回初始化好的那个对象
            return tea_obj
    
    
    class Teacher(object, metaclass=Mymeta):
        school = 'JSUN'
        
        def __init__(self, name, age):
            self.name = name
            self.age = age
        
        def score(self):
            print('%s is scoring' % self.name)
    
    
    tea2 = Teacher('qzk', 18)
    print(tea2.__dict__)  # {'name': 'qzk', 'age': 18}
  • 相关阅读:
    centos7安装docker-ce最新版
    输出第一个hello word程序(day1)
    centos7安装python3及ipython
    华为防火墙ping不通直连设备
    cisco网络设备基本命令
    linux中ftp
    查找你的域名DNS服务器
    Grafana 安装配置启动
    Jmeter 循环控制器
    CentOs 7查看端口占用情况,以及出现未找到命令的情况
  • 原文地址:https://www.cnblogs.com/qianzhengkai/p/10776792.html
Copyright © 2011-2022 走看看