• 1104 exec模块与元类的定义作用


    exec模块的补充

    1.定义

    python中的内置模块

    2.作用

    可以把 '字符串' 形式的python代码,添加到全局名称空间或局部名称空间中

    3.使用

    1. 文本形式的python 的源代码
    2. 全局的名称空间{}
    3. 局部名称空间{}
    1.python代码
    code='''
    global x
    x=10
    y=20
    def func():
    	pass
    '''
    
    2.全局名称空间字典
    global_dict = {'x':200}
    
    3.局部名称空间字典
    local_dict = {'y':100}
    
    4.调用exec
    exec(code,global_dict,local_dict)
    
    print(global_dict)
    print(local_dict)
    

    元类

    1.什么是元类

    元类就是类的类,chinese类的类是type,type是所有类的类,type就是一个元类

    1. **道** 即是 type
    2. **一** 即是 metaclass(元类,或者叫类生成器)
    3. **二** 即是 class(类,或者叫实例生成器)
    4. **三** 即是 instance(实例)
    5. **万物** 即是 实例的各种属性与方法,我们平常使用python时,调用的就是它们。
    

    创建类的两种方式

    1. 通过class关键字创建类,内部会调用type(),type帮我们创建一个自定义类
    2. 通过手动调用type()实例化得到自定义的类

    type创建类

    类名,父类,类内的属性方法
    class_name = '类名',class_base = (父类,),class_dict = {}
    我是谁,我来自哪里,又要到哪去.
    
    ***************************************************************
    # type创建类
        # 获得type元类的三大要素
    class_name='China'
    class_base = (object,)
    class_dict = {}
        # 创建exec语句
    code = '''
    country = "china"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def speak(self,name,age):
        print(f"speak {name} {age}华诞!......")
    '''
    # 创建exec传入
    exec(code,{},class_dict)
    china = type(class_name,class_base,class_dict) # 得到china类
    print(china)
    c = china("你好","70") # 实例化对象c
    c.speak("你好","70")   # 对象.方法调用  speak 你好 70华诞!......
    

    class创建类

    class 类名:
    	pass
    

    2.元类的作用

    元类可以帮我们控制类的创建

    3.怎么自定义创建元类

    1. 自定义一个元类,继承type,派生出自己的属性与方法
    2. 给需要使用的类,通过metaclass指定自定义好的元类class 类名(metaclass = '自定义的类')

    自定义创建元类

    class MyMetaclass(type):
        # 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的方法
        def __init__(self,class_name,class_base,class_dict):
            # Foo并没有被调用,metaclass=MyMetaclass调用元类,类在定义时会定义名称空间,所以__init__触发,打印
            print(class_name)   # 类名    Foo
            print(class_base)   # 父类    (<class 'object'>,)
            print(class_dict)   # 类的所有属性  {'__module__': '__main__', '__qualname__': 'Foo', 'x': 10, 'f1': <function Foo.f1 at 0x000001EF0423E9D8>}
            # 使用super()函数指向type,type需要what,where,go三个参数
            super().__init__(class_name,class_base,class_dict)
    
    
    # metaclass=   自定义的元类
    # 因为Foo继承了元类,所以必须手动继承object
    class Foo(object,metaclass=MyMetaclass):
        x = 10
        def f1(self):
            print('这是foo的打印.......')
    

    增加元类限制创建类的规则

    class MyMetaclass(type):
        # 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的方法
        def __init__(self,class_name,class_base,class_dict):
            #   1.判断定义类的首字母必须大写
            if not class_name.istitle():
                raise TypeError('类名必须首字母大小')
            #   2.控制类中必须有缩进
            if not class_dict.get('__doc__'):
                raise TypeError('类中必须书写注释!')
    
            # 使用super()函数指向type,type需要what,where,go三个参数
            super().__init__(class_name,class_base,class_dict)
    
    
    # metaclass=   自定义的元类
    # 因为Foo继承了元类,所以必须手动继承object
    class Foo(object,metaclass=MyMetaclass):
        '''这是注释,但是不能使用 "#" '''
        x = 10
        def f1(self):
            print('这是foo的打印.......')
    

    元类限制对象的调用

    # 对象调用时自动触发type 的__call__ 方法,call方法又会触发__new__,__init__来得到obj,通过重写覆盖父类的方法来限制对象的调用
        def __call__(self, *args, **kwargs):
            # 1.会调用__new__方法,创建一个空对象
            obj = object.__new__(self)
            # 2.会执行__init__方法,传参实例化
            obj.__init__(*args,**kwargs)
            return obj  # 将对象返回出去
    
    # 控制类的调用
    class MyMetaclass(type):
        # 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的方法
        def __init__(self,class_name,class_base,class_dict):
            # 使用super()函数指向type,type需要what,where,go三个参数
            super().__init__(class_name,class_base,class_dict)
    
        # 对象调用时自动触发type 的__call__ 方法,这里定义call方法,限制对象的调用
        def __call__(self, *args, **kwargs):
            # 1.会调用__new__方法,创建一个空对象
            obj = object.__new__(self)
            # 2.会执行__init__方法,传参实例化
            obj.__init__(*args,**kwargs)
            return obj  # 将对象返回出去
    
    # metaclass=   自定义的元类
    # 因为Foo继承了元类,所以必须手动继承object
    class Foo(object,metaclass=MyMetaclass):
        '''这是注释,但是不能使用 "#" '''
        x = 10
        def __init__(self,x,y):
            self.x = x
            self.y = y
        def f1(self):
            print('这是foo的打印.......')
    
    foo = Foo(20,30)    # 调用foo对象会触发__call__方法
    
  • 相关阅读:
    UVA 1400."Ray, Pass me the dishes!" -分治+线段树区间合并(常规操作+维护端点)并输出最优的区间的左右端点-(洛谷 小白逛公园 升级版)
    SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并
    洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)
    HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模
    HDU 3183.A Magic Lamp-区间找最小值-RMQ(ST)
    HDU 1231.最大连续子序列-dp+位置标记
    牛客网 牛客练习赛43 F.Tachibana Kanade Loves Game-容斥(二进制枚举)+读入挂
    CodeForce-811B Vladik and Complicated Book(水题)
    POJ1426——Find The Multiple (简单搜索+取余)
    POJ——3278 Catch That Cow(BFS队列)
  • 原文地址:https://www.cnblogs.com/fwzzz/p/11795650.html
Copyright © 2020-2023  润新知