zoukankan      html  css  js  c++  java
  • 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__方法
    
  • 相关阅读:
    软件测试之功能测试简单介绍
    如果编程语言是女孩,你猜C语言是萝莉还是御姐?
    C++ C、C++、C#、VC、VC.net以及VC++有什么区别和联系?
    程序员如何避免陷入内卷?从以下三个方面着手
    懒惰使人进步,UNIX 和 Linux 新系统的诞生只是意外
    编程学习必备:C++ 学习的 11 本经典书籍推荐
    初入职场,菜鸟程序员如何才能成为业界大牛,给你提供思路方法。
    TIOBE 12月编程语言: Python、Java战况激烈, C语言:我自岿然不动
    C++基础知识篇:C++ 数字
    二本毕业程序员鄙视清北毕业生,嘲笑水货一抓一大把,你怎么看?
  • 原文地址:https://www.cnblogs.com/fwzzz/p/11795650.html
Copyright © 2011-2022 走看看