zoukankan      html  css  js  c++  java
  • eval、exec及元类、单例实现的5种方法

    eval内置函数

    # 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内置函数

    # exec应用场景
    # 1.执行字符串没有执行结果(没有返回值)
    # 2.将执行的字符串中产生的名字形成对应的局部名称空间
    # 3.可以操作全局与局部两个名称空间,一般不用关心全局名称空间

    source = '''
    name = 'Bob'
    age = 20
    '''
    class A:
       pass
    a = A()

    dic = {}
    exec(source, {}, dic)
    a.__dict__ = dic   # dic = {‘name': 'Bob', 'age': 20}
    print(a.__dict__)
    print(a.name)
    print(a.age)

     

    元类

    # 元类:类的类
    # 通过class产生的类,也是对象,而元类就是用来产生该对象的类
    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', (), l_d)
    print(Student)

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

     

     

    自定义元类

    # 元类:所有自定义的类本身也是对象,是元类的对象,所有自定义的类本质上是由元类实例化出来了
    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 A(type):
    def __init__(cls, class_name, bases, namespace):
    print('父类init run')
    super().__init__(class_name, bases, namespace)

    def __call__(cls, *args, **kwargs):
    print('父类的call run')
    obj = object.__new__(cls)
    cls.__init__(obj, *args, **kwargs)
    # obj = super().__call__(*args, **kwargs)
    return obj

    def __new__(mcs, *args, **kwargs):
    print('父类的new run')
    obj = super().__new__(mcs, *args, **kwargs)
    return obj


    class B(metaclass=A):
    def __init__(self, name):
    print('子类的init run')
    self.name = name

    def __new__(cls, *args, **kwargs):
    print('子类的new run')
    obj = object.__new__(cls)
    return obj


    a = B('bob')
    print(a.__dict__)

    '''
    父类的new run
    父类init run
    父类的call run
    子类的new run
    子类的init run
    {'name': 'bob'}
    '''
     

     

    单例

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

    ## 单例

    ```python
    #实现单例方法1--类方法及类封装属性
    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)

    #实现单例方法2--装饰器
    ```

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

    #实现单例方法3--重用__new__方法
    ```

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

    #实现单例方法4--模块导入(原理:一个模块只有在第一次导入时才会编译执行,之后都是从内存中寻找)
    ```

    ```python
    # single_module.py
    class Single:
       pass
    singleton = Single()

    # 测试文件
    from single_module import singleton
    print(singleton)
    print(singleton)


    #实现单例方法5--自定义元类,并将__call__方法重用
    class SingleMeta(type):
       __instance = None
       def __call__(cls, *args, **kwargs):
           if SingleMeta.__instance == None:
               SingleMeta.__instance = object.__new__(cls)
               cls.__init__(SingleMeta.__instance, *args, **kwargs)
           return SingleMeta.__instance


    class Songs(metaclass=SingleMeta):
       def __init__(self):
           pass
       pass


    s1 = Songs()
    s2 = Songs()
    print(s1, s2)

    ```
  • 相关阅读:
    数据结构概论
    html基础:有序列表 框架集 form表单
    html基础:定义 图片 表格
    给出2个数和一个运算符号,用函数求结果
    百钱买百鸡问题
    九九乘法表
    过路问题
    php基础:控制结构 总结
    php基础:变量,运算符总结
    php基础:数据库的含义和基本操作 增 删 改 查
  • 原文地址:https://www.cnblogs.com/maoruqiang/p/10779952.html
Copyright © 2011-2022 走看看