zoukankan      html  css  js  c++  java
  • python基础语法20 面向对象5 exec内置函数的补充,元类,属性查找顺序

    exec内置函数的补充

    exec: 是一个python内置函数,可以将字符串的代码添加到名称空间中;
      - 全局名称空间
      - 局部名称空间

      exec(字符串形式的代码, 全局名称空间, 局部名称空间)

    # 使用exec, code相当于局部名称空间中的名字
    code = '''
    global x
    x = 100
    
    y = 20
    def func():
        pass
    
    def __init__():
        pass
    '''
    
    # 自定义的全局名称空间
    global_dic = {
        'x': 10000
    }
    
    # 自定义的局部名称空间
    local_dic = { 'y':300
    }
    
    # print(global_dic)
    #
    # print(local_dic)
    
    exec(code, global_dic, local_dic)
    print(global_dic)   # {'x': 100, ...} 此处全局变量1000被code中x=100替换
    
    # print(local_dic)
    # {'y': 20, 'func': <function func at 0x00000000003D1E18>, '__init__': <function __init__ at 0x00000000023789D8>}
    # 局部空间y=300被code中y=20替换

    元类

    1.什么是元类?
      - 类的类就是type, 其实type就是元类;

    2.元类的作用?

      - 元类可以控制类的创建过程!

    3.如何创建元类以及使用?

    # 1.一切皆对象
    list1 = []  # list1 = list([])
    # print(type(list1))  # <class 'list'>
    
    
    # 2.自定一个类
    class Chinese(object):
        country = 'china'
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    
    p_obj = Chinese('tank', 17, 'male')
    # print(type(p_obj))  # <class '__main__.Chinese'>
    print(Chinese)  # 类本质上也是一个对象,因为在python中 一切皆对象 ;
    # print(type(Chinese))  # <class 'type'> 说明Chinese类是有type实例化的对象
    # 3.如何产生类的:
    # 1) 通过class关键字产生类
    # 2) 通过调用type类: type()  ---> obj ---> Chinese
    
    # what: 指的是类名
    # bases: 继承的父类 (object, )
    # dict: 类的名称空间
    
    code = '''
    country = 'china'
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
    '''
    # class_attr
    class_attr = {}
    exec(code, {}, class_attr)
    
    # type(类的名字, 类的基类, 类的名称空间) ----> 类 ---> 对象
    obj = type('Chinese', (object, ), class_attr)  # def __init__(what, bases=None, dict=None)
    # print(obj)
    Chinese = obj
    print(Chinese)  # <class '__main__.Chinese'>
    chinese_obj = obj('tank',18,'male')
    print(chinese_obj.country)  # china

    1.什么是元类?
    类的类就是type, 其实type就是元类;

    2.为什么要使用元类???
    元类可以控制类的创建过程!

    # type是python内置的元类
    # 自定义一个元类
    class MyMetaClass(type):
    
        # 控制类的创建
        # 优酷需要用到的部分;
        def __init__(self, class_name, class_bases, class_dict):  # self, obj
            print(type(class_name))
            # print(class_name.istitle())
            if not class_name.istitle():
                raise NameError('类的首字母必须大写!')
            if not class_dict.get('__doc__'):
                raise TypeError('必须给我写注释!!!')
    
            # 必须将类中的类名、类的基类、类的名称空间,一并返回给 type中的__init__
            super().__init__(class_name, class_bases, class_dict)
    
        # 了解: 元类更深层次的作用
        # 控制调用类的行为
        # 为什么调用类就一定会产生一个空对象,为什么一定会执行__new__
        # 其实就是type内部一定会调用一次__call__,由__call__来帮你调用__new__。
        # 元类中的__call__就是创建类的过程!!!
        def __call__(self, *args, **kwargs):
            print(args)  # Foo类括号中的值
            # 1.造一个空对象obj
            obj = object.__new__(self)  # 创造一个空的对象  # self ---> User
            print(obj.__dict__, 1111111)
            # 2.调用类时,__call__会立马调用User.__init__, 并且将obj连同Foo括号内的参数一同传给__init__
            self.__init__(obj, *args, **kwargs)
            # return一个真正创建的对象
            return obj
    
    # obj = MyMetaClass()
    # obj()  # obj() ----> User(10, 20)  ----> user_obj
    # 被控制类在定义阶段  类名(metaclass=自定义的元类) ---> 会将当前类的
    # 1)类名、2)基类、3)类的名称空间   一并 传给 自定义的元类
    # metaclass ---> 自定义的元类 ---> 调用自定义的元类(类名, 基类, 类的名称空间)
    # type(类名, 基类, 类的名称空间)
    
    class User(object, metaclass=MyMetaClass):  # MyMetaClass(User, (object, ), {'x':10})
    
        '''tank是真的很帅啊,真的舍不得你们啊!!!'''
        def __init__(self):
            pass
        x = 10
    
    obj = User()
    print(obj)
    '''

      <class 'str'>
      ()
      {} 11111111
      <__main__.User object at 0x000000000258C4E0>

    '''

    属性查找顺序

    class Mymeta(type):  # 但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
        # n=444
        def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类
            # 1. 先产生一个空对象
            tea_obj = self.__new__(self)  # tea_obj是OldboyTeacher这个类的对象
            # print(self.__new__ is object.__new__)
            # tea_obj=object.__new__(self)
    
            # 2. 执行__init__方法,完成对象的初始属性操作
            self.__init__(tea_obj, *args, **kwargs)
            # 3. 返回初始化好的那个对象
            return tea_obj
    
    
    class Bar:
        # n = 33
        pass
    
    class Foo(Bar):
        # n = 222
        pass
    
    class OldboyTeacher(Foo, metaclass=Mymeta):  # OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
        # n = 111
        school = 'Oldboy'
    
        def __init__(self, name, age, sex):
            self.name = name #None.name='egon'
            self.age = age
            self.sex = sex
    
        def score(self):
            print('%s is scoring' % self.name)
    
        def __new__(cls, *args, **kwargs):
            # print('=====>')
            return super().__new__(cls)
    
    tea1 = OldboyTeacher('egon', 18, 'male')
    # print(tea1)
    print(tea1.__dict__)
    
    # print(OldboyTeacher.n)
    
    # print(object.__new__)

     图示顺序:

     

  • 相关阅读:
    poj1179 Polygon
    poj2677 Tour
    MariaDB10多实例--mysqld_multi
    MariaDB10源码安装
    linux下php+freetds连接SQL server2012
    MariaDB yum安装
    mongoDB yum安装
    pxe 引导clonezilla live万能备份与还原
    (转) pppd 中文man页面
    Unix-like DisplayManager/LoginManager/WindowManager
  • 原文地址:https://www.cnblogs.com/ludingchao/p/12039950.html
Copyright © 2011-2022 走看看