zoukankan      html  css  js  c++  java
  • 元类

    讲元类前先说说两个内置函数evel、exec

    evel平时会用到,exec平时用不太到但是在元类中会用到

    eval内置函数的使用场景

        1、执行字符串会得到相应的执行结果

        2、一般用于类型转化,得到dict、list、tuple等

    dic_str = "{'a': 1, 'b': 2, 'c': 3}"
    list_str = "[1, 2, 3, 4, 5]"
    tuple_str = "(1, 2, 3, 4, 5)"

    with open('1.txt', 'r', encoding='utf-8') as rf:
    data_str = rf.read()
    # print(data_str, type(data_str))

    # import json
    # res = json.loads(data_str)
    # print(res, type(res))                                如果是严格的json,则拿json来转换

    # "{'a': 1, 'b': 2, 'c': 3}" => {'a': 1, 'b': 2, 'c': 3}
    # res = eval(data_str)
    # print(res, type(res))

    exec内置函数的使用场景

        1、执行字符窜,没有执行结果(没有返回值)

        2、将执行的字符串中产生的名字形成对应的局部名称空间

    s = '''
    my_a = 10
    my_b = 20
    def __init__(self):
    pass
    @classmethod
    def print_msg(msg):
    print(msg)
    '''
    # g_dic = {}
    l_dic = {}
    exec(s, {}, l_dic)
    print(l_dic)

    类的名称空间的控制

    # Python中万物皆对象,所有用来创建对象的类,本身也是对象,类是type类的对象
    # type类叫做元类,是所有元类的基类
    # 元类:造类的类 - 类的类
    # -- 控制类的产生
    # -- 控制类的对象的产生

    dic = {}
    exec(s, {}, dic)

    C = type('C', (object, ), dic)
    print(C, type(C), C.__bases__)
    print(C.__dict__)

    c1 = C()
    print(c1.my_a)
    C.print_msg('12345')

    自定义元组

      

    class CountError(Exception):
    pass


    class MyMeta(type):

    # 自定义元类,重写init方法的目的:
    # 1.该方法是从type中继承来的,所以参数同type的init
    # 2.最终的工作(如果开辟空间,如果操作内存)还是要借助type
    # 3.在交给type最终完成工作之前,可以对类的创建加以限制 *****
    def __init__(cls, class_name: str, bases, namespace):
    # print(cls)
    # print(class_name)
    print(bases)
    # print(namespace)
    # 需求:由给元类控制的类的类名必须首字母大写
    if not class_name.istitle():
    raise NameError('名字首字母必须大写')
    # 需求:定义类是必须明确父类
    if len(bases) == 0:
    raise CountError('父类必须明确')

    # super(MyMeta, cls).__init__(class_name, bases, namespace)
    super().__init__(class_name, bases, namespace)


    # 自定义元类,重写call方法的目的:
    # 1.被该元类控制的类生成对象,会调用元类的call方法
    # 2.在call中的返回值就是创建的对象
    # 3.在call中
    # -- 通过object开辟空间产生对象
    # -- 用被控制的类回调到自己的init方法完成名称空间的赋值
    # -- 将修饰好的对象反馈给外界
    def __call__(cls, *args, **kwargs):
    print('call fn run')
    obj = object.__new__(cls)
    # 需求:所有通过该元类控制的类产生的对象都有meta_name该属性
    obj.meta_name = cls.__name__
    # obj.name = args[0]
    # 调回当前被控制的类自身的init方法,完成名称空间的赋值
    cls.__init__(obj, *args, **kwargs)
    return obj

                       单例:一个类只能产生一个实例
    # 为什么要有单例:
    # 1.该类需要对象的产生
    # 2.对象一旦产生,在任何位置再实例化对象,只能得到第一次实例化出来的对象


    class Songs():
    # def __init__(self, song_name):
    # self.song_name = song_name

    def run(self):
    pass
    def pause(self):
    pass

    song = Songs()
    song.run()

    # ....

    song = Songs()
    song.pause()

  • 相关阅读:
    Android Service
    Java 关键字 static final
    Django | mysql修改个别表后save()报错
    Django | Unable to get repr for <class 'django.db.models.query.QuerySet'>
    MySQL | linux中数据库导出和导入
    MySQL | 查看log日志
    python | log日志
    python | 网络编程(socket、udp、tcp)
    Python | 异常处理
    Python | 单例模式
  • 原文地址:https://www.cnblogs.com/SlookUp/p/10776536.html
Copyright © 2011-2022 走看看