zoukankan      html  css  js  c++  java
  • 内置方法 eval | exec 元类 单例

    eval与exec内置方法

      将字符串作为执行目标,得到响应结果

      eval常用作类型转换:该函数执行完有返回值

      exec拥有执行更复杂的字符串:可以形成名称空间

     eval内置函数的使用场景:
       1.执行字符串会得到相应的执行结果
       2.一般用于类型转化,得到dict、list、tuple等

    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))

    exec应用场景
     1.执行字符串没有执行结果(没有返回值)
     2.将执行的字符串中产生的名字形成对应的局部名称空间

    source = '''
    name = 'Bob'
    age = 20
    '''
    class A:
        pass
    a = A()
    
    dic = {}
    
    # 可以操作全局与局部两个名称空间,一般不用关心全局名称空间
    exec(source, {}, dic)
    a.__dict__ = dic
    print(a.__dict__)   # {'name': 'bob', 'age': 20}
    print(a.name)
    print(a.age)

    元类

    元类:类的类
      通过class产生的类,也是对象,而元类就是用来产生该对象的类

      类是type的对象,可以通过type(参数)来创建类

    local_str = """
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def study(self):
        print(self.name + '在学习')
    """
    local_dic = {}
    exec(local_str, {}, local_dic)
    Student = type('Student', (), local_dic)   # 产生一个Student类
    print(Student)

    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()

    自定义元类

      所有自定义的类本身也是对象,是元类的对象,所有自定义的类本质上是由元类实例化出来了

      控制类的产生过程,以及该类对象的产生过程

    # 元类:所有自定义的类本身也是对象,是元类的对象,所有自定义的类本质上是由元类实例化出来了
    Student = type('Student', (object, ), namespace)
    
    class MyMeta(type):
        # 在class Student时调用:Student类的创建 => 来控制类的创建
        
        # 自定义元类,重写init方法的目的:
        # 1.该方法是从type中继承来的,所以参数同type的init
        # 2.最终的工作(如开辟空间,如操作内存)还是要借助type
        # 3.在交给type最终完成工作之前,可以对类的创建加以限制 *****
        def __init__(cls, class_name, bases, namespace):
            # 目的:对class_name | bases | namespace加以限制 **********************
            super().__init__(class_name, bases, namespace)
        
        # 在Student()时调用:Student类的对象的创建 => 来控制对象的创建
        
        # 自定义元类,重写call方法的目的:
        # 1.被该元类控制的类生成对象,会调用元类的call方法
        # 2.在call中的返回值就是创建的对象
        # 3.在call中
        #       -- 通过object开辟空间产生对象
        #       -- 用被控制的类回调到自己的init方法完成名称空间的赋值
        #       -- 将修饰好的对象反馈给外界
        def __call__(cls, *args, **kwargs):
            # 目的:创建对象,就可以对对象加以限制 **********************
            obj = object.__new__(cls)  # 通过object为哪个类开辟空间
            cls.__init__(obj, *args, **kwargs)  # 调回当前被控制的类自身的init方法,完成名称空间的赋值
            return obj
    
    # 问题:
    # 1.继承是想获得父级的属性和方法,元类是要将类的创建于对象的创建加以控制
    # 2.类的创建由元类的__init__方法控制
    #        -- 元类(class_name, bases, namespase) => 元类.__init__来完成实例化
    # 3.类的对象的创建由元类的__call__方法控制
    #         -- 对象产生是需要开辟空间,在__call__中用object.__new__()来完成的
    class Student(object, metaclass=MyMeta):
        pass
    
    # class Student:  <=>  type(class_name, bases, namespace)

      控制类、类的对象 产生过程

    class MyMeta(type):
        # 控制类的创建过程
        def __init__(cls, class_name, bases, namespace):
            print(cls, class_name, bases, namespace)
            super().__init__(class_name, bases, namespace)
    
        def __call__(cls, *args, **kwargs):
            obj = object.__new__(cls)
            cls.__init__(obj, *args, **kwargs)
            return obj
    
    # Student类与Student类的对象产生都可以备元类MyMeta控制
    class Student(metaclass=MyMeta):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    stu = Student('owen', 18)
    print(stu.name)

    元类的应用

    # 单例1
    class
    MyMeta(type): def __call__(cls, *args, **kwargs): if not hasattr(cls, 'instance'): cls.instance = cls.__new__(cls) cls.instance.__init__(*args, **kwargs) return cls.instance class A(metaclass=MyMeta): def __init__(self): self.ip = '1.1.1.0'

    单例

      一个类只能产生一个实例
      为什么要有单例:
        1.该类需要对象的产生
        2.对象一旦产生,在任何位置再实例化对象,只能得到第一次实例化出来的对象
        3.在对象唯一创建后,可以通过属性修改或方法间接修改属性,来完成数据的更新,不能通过实例化方式更新数据

    # 单例2
    class
    Song: __instance = None def __init__(self): pass @classmethod def getInstance(cls): if cls.__instance == None: cls.__instance = cls() return cls.__instance s1 = Song.getInstance() s2 = Song.getInstance() print(s1, s2)

     # 单例3

    def singleton(cls):
        _instance = None
        def getInstance(*args, **kwargs):
            nonlocal _instance
            if _instance == None:
                _instance = cls(*args, **kwargs)
            return _instance
        return getInstance
    
    @singleton
    class A: def __init__(self, num): self.num = num

    print(A(1), A(2), A(3))
    print(A(1).num, A(2).num, A(3).num)   # 1 1 1

     # 单例4

    class A:
        __instance = None
        def __new__(cls, *args, **kwargs):
            if cls.__instance == None:
                cls.__instance = super().__new__(cls)
            return cls.__instance
    print(A(), A())

     # 单例5

    # single_module.py
    class Single:
        pass
    singleton = Single()
    
    # 测试文件
    from single_module import singleton
    print(singleton)
    print(singleton)
  • 相关阅读:
    基于Jquery+Ajax+Json+高效分页
    前端购物车框架(精髓篇)
    基于C#操作Word文档中的Bookmark
    C# 方法中的this参数
    Asp.Net 全局变量
    winform 多表头的实现
    2012年2月
    在UpdatePanel上使用FileUpload上传文件(转载)
    2011年总结和2012年计划
    javascript备注
  • 原文地址:https://www.cnblogs.com/zhouyongv5/p/10776467.html
Copyright © 2011-2022 走看看