zoukankan      html  css  js  c++  java
  • 优酷:exec 补充,元类,优酷构架,ORM。

    exec 补充

    exec 模块的补充

    1.exec是什么?

    exec 是一个python内置模块。

    2.exec 的作用;

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

    """
    x = 10
    def func1():
    	pass
    """
    

    3.怎么用:

    参数1:字符串形式的python代码

    参数2:全局名称空间字典

    参数3:局部名称空间字典

    调用exec()

    代码:

    # 全局名称空间
    # # 1.文本形式的python代码
    code = '''
    global x
    x = 10
    y = 20
    '''
    #2.全局的名称空间{}
    globals_dict = {'x':200}
    
    # 3.局部名称空间{}
    locals_dict = {}
    
    exec(code,globals_dict,locals_dict)   # 用exec 不仅打印全局的代码,还打打印了内置的代码。
    print(globals_dict)
    
    
    
    局部名称空间{}
    code = '''
    global x
    x = 100
    y = 200
    def func():
        pass
    '''
    #2.全局的名称空间{}
    globals_dict = {}
    # 3.局部名称空间{}
    locals_dict = {}
    
    exec(code,globals_dict,locals_dict)   # 用exec 不仅打印的代码,还打打印了内置的代码。
    
    print(globals_dict)
    

    元类

    在 python中,一切接是对象。

    """

    创建类有两种方法:

    1.通过class关键之创建类,内部会自动调用type(), type 帮我们创建一个自定义类

    2.通过手动调用type()实列化得到自定义的类。

    """

    #  what: 类名 --> type对象的名称
    #  bases: --> 基类/父类
    #  dict: --> 类的名称空间
    手动调用:(通过class关键字创建的)  建议以后多使用此方法。
    class Chinses:
        country = 'China'
    
        def __init__(self,name,age):
            self.name = name
            self.age =age
    
        def speak(self):
            print('speak  chinese....')
    
    p1 = Chinses('tank',18)# 自动调用
    print(Chinese)
    结果:
    <class '__main__.Chinses'>
    
    
    自动调用  (通过type手动创建的)
    class_name = 'Chinese'
    class_base = (object,)
    class_dict = {}
    code = '''
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    def speak(self):
        print("speak Chinese...")
    '''
    exec(code,{},class_dict)
    Chinses = type(class_name,class_base,class_dict)
    print(Chinses)
    
    结果:
    <class '__main__.Chinses'>
    

    1.什么是元类?

    元类就是类的类,Chinese类的类是type,type是所有类的类,type就是一个元类。

    2.元类的作用?

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

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

    3.怎么自定义创建元类:

    1. 自定义一个元类,继承type,派生出自己的属性与方法。

    2. 给需要使用的类,通过metaclass指定自定义好的元类。class Chinese(metaclass='自定义的元类'):'''

    # 自定义元类
    class MyMeta(type):
        # 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的__init__方法。
        # 控制了类的定义
        def __init__(self, class_name, class_base, class_dict):
            # print(class_name)
    
            # 判断字符串首字母是否大写
            if not class_name.istitle():
                raise TypeError('类的首字母必须大写!')
    
            # 控制类中必须要有注释
            if not class_dict.get('__doc__'):
                raise TypeError('类内部必须要写注释!')
    
            # print(class_base)
            # print(class_dict)
            super().__init__(class_name, class_base, class_dict)
    
        # 模拟type元类内部做的事情
        # 元类触发的__call__可以控制类的调用。调用__call__会触发以下两点
        def __call__(self, *args, **kwargs):
            # 1.会调用__new__()--> obj, 会创建一个空对象。
            obj = object.__new__(self)
            # 2.会执行__init__(obj, *args, **kwargs),
            obj.__init__(*args, **kwargs)
            return obj
    
        # 可以通过元类内部的__new__控制对象的创建
        def __new__(cls, *args, **kwargs):
            pass
    
    class Bar:
        pass
    

    优酷构架

    ATM

    ​ 用户试图层

    ​ 接口层

    ​ 数据层

    ​ dict

    ​ json

    ​ 优点:数据可以跨平台。

    ​ 缺点:不能存在对象,也不能直接获取对象。 {.......}

    ​ 不能通过"对象.属性"的方式 存 取值。

    ​ 存储速度比pickle慢。

    选课系统

    ​ 用户试图层

    ​ 接口层

    ​ 数据层

    ​ models:

    ​ obj

    ​ pickle

    ​ 优点:可以通过对象''属性''的方式 存 取值。

    ​ 能存对象,也能直接获取对象。

    ​ pickle

    ​ 缺点:不能跨平台。

    优酷

    用户试图层

    接口层

    数据层

    ​ 存储对象 --》 dict ---》json ---》mysql

    ​ mysql ----》 json ----》dict ----》 获取对象

    ORM

    ORM:

    ORM:对象关系映射 ---> 映射到数据库MySQL中的数据表

    类名 ---> 表名

    对象 ---> 一条记录

    对象.属性 ---> 字段

    模拟Django的ORM,为了,将数据库的 增、删、改、查,全部封装成一个个的方式,比如: save, delete, update, select。

    1.创建字段的类型,将数据库的 增,删,改,查,全部封装。

    # 1.创建字段的类型, 对应数据表中的一个个字段的创建规范
    class Field:
        def __init__(self, name, column_type, primary_key, default):
            self.name = name
            self.column_type = column_type
            self.primary_key = primary_key
            self.default = default
    
    # Integer
    class IntegerField(Field):
        def __init__(self, name, column_type='int', primary_key=False, default=0):
            super().__init__(name, column_type, primary_key, default)
    
    # String
    class StringField(Field):
        def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None):
            super().__init__(name, column_type, primary_key, default)
    
    class Father:
        def __init__(self, *args, **kwargs):
            self.id = id
            self.username = args[0]
            self.password = args[1]
            self.photo = args[2]
    
    class Models(dict):
    
        # 会在 对象.属性 没有时 触发
        def __getattr__(self, item):
            print(item, '调用没有的属性时会触发...')
            # 将字典中key对应的值,返回给对象
            return self.get(item)  # dict_obj.get(key)
    
        # 在 对象.属性=值 时触发
        def __setattr__(self, key, value):
            print(key, value)
            # 给字典对象本身赋值
            self[key] = value
    
    # 创建数据表类
    # 用户表类
    class User(Models):  # ---> 表名
        # 强调: 最好与字段类型的name属性同名
        user_id = IntegerField(name='user_id')
        user_name = StringField(name='name')  # tank
        pwd = StringField(name='pwd')  # 123
        pass
    
    # 电影表类
    class Movie(Models):
        pass
    
    user = User(id='007', name='tank', pwd='123')  # ---> 一条记录
    # print(user)
    # print(type(user))
    
    movie = Movie(m_id='1', movie_name='jason真实写真')
    print(movie)
    print(type(movie))
    
    # 字典的取、存值方式
    print(user['id'])
    user['age'] = 18
    print(user.get('id'))
    print(user.get('age'))
    
    user.age = 18  # {key: value}
    print(user.age)
    
    user.sex = 'male'
    print(user.sex)  # None ---> return self.get(sex) --> 'male'
    print(user['sex'])  # male
    print(user.__dict__)
    
    # 结果:
    {'m_id': '1', 'movie_name': 'jason真实写真'}
    <class '__main__.Movie'>
    007
    007
    18
    age 18
    age 调用没有的属性时会触发...
    18
    sex male
    sex 调用没有的属性时会触发...
    male
    male
    {}
    
    
    '''
    问题1: 解决代码荣誉问题,比如有100张表,需要写100次__init__。
    解决1: 继承一个父类,父类中定义一个__init__。
    
    问题2: 无法预测每一张表中的字段是什么,无法通过父类的__init__解决问题。
    解决2: 通过继承字典,内部的__init__, 可以接受“任意个数”的“关键字参数”。
    
    
    问题3: 继承字典的类实例化的对象,无法通过“对象.属性”的方式存取值。
    解决3: 通过__setattr__,__getattr__来实现,让字典对象与普通对象一模一样,并且具备字典原有的特性。
        
    '''
    
    
    问题1: 解决代码荣誉问题,比如有100张表,需要写100次__init__。
    解决1: 继承一个父类,父类中定义一个__init__。
    
    问题2: 无法预测每一张表中的字段是什么,无法通过父类的__init__解决问题。
    解决2: 通过继承字典,内部的__init__, 可以接受“任意个数”的“关键字参数”。
    
    class Field:
        def __init__(self,name,colunm_type,primary_key ,default):
            self.name =name
            self.column_type = colunm_type
            self.primary_key = primary_key
            self.default = default
    
    class IntergerField(Field):
        def __init__(self,name,colunm_type='int',primary_key = False,default=0):
            super().__init__( name, colunm_type , primary_key, default)
    
    class StringField(Field):
        def __init__(self,name,colunm_type='varchar(64)',primary_key = False,default=None):
            super().__init__(name, colunm_type, primary_key, default)
    
    class User(dict):
    
        pass
    
    class Moive(dict):
    
        pass
    
    user = User(id = '007',name='tank',pwd = '123')
    print(user)
    print(type(user))
    print(user['id'])#  只打印索引key的值  007
    moive = Moive(m_id = '1',movie_name = 'tank真是写真')
    print(moive)
    print(type(moive))
    print(user.get('id'))  #只打印索引key的值   007
    
    #结果:
    {'id': '007', 'name': 'tank', 'pwd': '123'}
    <class '__main__.User'>
    007
    {'m_id': '1', 'movie_name': 'tank真是写真'}
    <class '__main__.Moive'>
    007
    
    问题1: 解决代码荣誉问题,比如有100张表,需要写100次__init__。
    解决1: 继承一个父类,父类中定义一个__init__。
    
    问题2: 无法预测每一张表中的字段是什么,无法通过父类的__init__解决问题。
    解决2: 通过继承字典,内部的__init__, 可以接受“任意个数”的“关键字参数”。
    
    问题3: 继承字典的类实例化的对象,无法通过“对象.属性”的方式存取值。
    解决3: 通过__setattr__,__getattr__来实现,让字典对象与普通对象一模一样,并且具备字典原有的特性。
    
    # 1.创建字段的类型, 对应数据表中的一个个字段的创建规范
    class Field:
        def __init__(self, name, column_type, primary_key, default):
            self.name = name
            self.column_type = column_type
            self.primary_key = primary_key
            self.default = default
    
    
    # Integer
    class IntegerField(Field):
        def __init__(self, name, column_type='int', primary_key=False, default=0):
            super().__init__(name, column_type, primary_key, default)
    
    
    # String
    class StringField(Field):
        def __init__(self, name, column_type='varchar(64)', primary_key=False, default=None):
            super().__init__(name, column_type, primary_key, default)
                   
    
    '''
    元类需要处理的问题:
        1.一张表必须要有一个表名。
        2.给数据表类,强制必须要有一个主键,主键必须是唯一的。
        3.将数据表中,所有的字段对象,都存放在一个独立的字典中
            存不是目的,目的是为了取值方便。
    '''
    
    
    class OrmMetaClass(type):
        # def __new__(cls, *args, **kwargs):
        # print(args, 'args............')
        # print(kwargs, 'kwargs........')
    
        # OrmMetaClass(class, class_name, class_base, class_dict)
    
        def __new__(cls, class_name, class_base, class_dict):
            # print(class_name, '类名--》表名')
            # print(class_base, '基类/父类')
            # print(class_dict, '类的名称空间')
    
            # 过滤Models类
            if class_name == 'Models':
                # models类中,什么都不做,将类原路返回。
                return type.__new__(cls, class_name, class_base, class_dict)
    
            # 1.一张表必须要有表名
            # 假如table_name没有值,则将类名当做表名
            table_name = class_dict.get('table_name', class_name)  # get--> self.table_name
    
            # 2.主键名
            primary_key = None
    
            # 3.定义一个空字典, 专门用来存放字段对象
            mappings = {}
    
            # 遍历名称空间中所有的属性
            for key, value in class_dict.items():
                # print(key, value)
                # 除了有字段,还有其他字段以外的属性
                # 过滤字段对象以外的内容
                if isinstance(value, Field):
                    mappings[key] = value
    
                    # 判断字段对象primary_key是否为True
                    if value.primary_key:
                        # 先判断初识的primary_key是否有值
                        # 判断主键是否已存在
                        if primary_key:
                            raise TypeError('只能有一个主键!')
    
                        # 若主键不存在,则给primary_key赋值
                        primary_key = value.name
    
            # 节省资源: 因为mappings与原类中名称空间中的属性重复,为了节省内存,剔除重复的属性。
            for key in mappings.keys():
                class_dict.pop(key)
    
            # 判断是否有主键
            if not primary_key:
                raise TypeError('必须有一个主键')
    
            # 给类的名称空间添加表名
            class_dict['table_name'] = table_name
            # 给类的名称空间添加主键名
            class_dict['primary_key'] = primary_key
            # 给类的名称空间添加一个mappings字典,字典中拥有所有字段属性
            class_dict['mappings'] = mappings
            return type.__new__(cls, class_name, class_base, class_dict)
    
    
    class Models(dict, metaclass=OrmMetaClass):  # OrmMetaClass(Models, Models_name, base, class_dict)
        def __getattr__(self, item):
            print(item, '调用没有的属性时会触发...')
            # 将字典的值,返回
            return self.get(item)
    
        def __setattr__(self, key, value):
            print(key, value)
            self[key] = value
    
    
    # 用户表类
    class User(Models):  # ---> 表名
        # table_name = 'user_info'
        # 强调: 最好与字段类型的name属性同名
        user_id = IntegerField(name='user_id', primary_key=True)
        user_name = StringField(name='name')
        pwd = StringField(name='pwd')
        pass
    
    
    # 用户表类
    class Movie(Models):  # ---> 表名
        # table_name = 'user_info'
        # 强调: 最好与字段类型的name属性同名
        user_id = IntegerField(name='user_id', primary_key=True)
        user_name = StringField(name='name')
        pwd = StringField(name='pwd')
        pass
    
    
    if __name__ == '__main__':
    print(User.__dict__)
    
    元类需要处理的问题:
        1.一张表必须要有一个表名。
        2.给数据表类,强制必须要有一个主键,主键必须是唯一的。
        3.将数据表中,所有的字段对象,都存放在一个独立的字典中
            存不是目的,目的是为了取值方便。
    
    {'__module__': '__main__', 'table_name': 'User', 'primary_key': 'user_id', 'mappings': {'user_id': <__main__.IntegerField object at 0x0000020CD1F52508>, 'user_name': <__main__.StringField object at 0x0000020CD1F523C8>, 'pwd': <__main__.StringField object at 0x0000020CD1EF2AC8>}, '__doc__': None}
    
    
  • 相关阅读:
    NestingQuery
    Repeat
    GenericQuery
    StringOpr
    RHEL5.6 安装 virtualbox
    DNS的资料总结
    drop delete truncate 区别
    Linux Shell命令ulimit的用法
    OSI及TCP/IP的概念和区别
    shell:读取文件的每一行内容并输出
  • 原文地址:https://www.cnblogs.com/WQ577098649/p/11795211.html
Copyright © 2011-2022 走看看