• day 38小结


    exec 模块的补充

    ​ exec是python 的一个内置模块

    ​ exec的作用

    x = 10
    def func():
    	pass
    # 可以把"字符串形式" 的python代码, 添加到全局空间或局部名称空间中.
    

    ​ 用法:
    ​ 参数一: 字符串形式的python代码
    ​ 参数二: 全局名称空间字典
    ​ 参数三: 局部名称空间字典
    ​ 调用exec()

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

    元类

    什么是元类
    元类就是类的类,Chinese类的类就是type,type是所有类的类,type就是元类

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

    怎么自定义创建一个元类:
    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
    
    # metaclass ---> 自定义的元类
    # 因为Foo类继承了元类,必须手动继承object
    class Foo(Bar, metaclass=MyMeta):  # MyMeta(Foo, Foo_name, (Bar, ), foo_dict)
        '''
        这是一个Foo类
        '''
        # 摊开坦克
        x = 10
    
        def __init__(self, y, z):
            self.y = y
            self.z = z
    
        def f1(self):
            print('from Foo.f1...')
    
    
    foo = Foo(20, 30)  # 调用Foo对象,会触发__call__
    

    优酷框架

    • ATM

      • 用户试图层

      • 接口层

      • 数据层

        • dict

        • json

          优点: 数据可以跨平台
          缺点: 不能存对象,也不能直接获取对象.
          不能通过"对象.属性" 的方式存,取值

    • 选课系统

      • 用户视图层

      • 接口处

      • 数据层

        • models
          • obj
        • pickle

        优点: 可以通过"对象.属性" 的方式存,取值
        缺点: 不能跨平台

    • 优酷

      • 用户视图层
      • 接口层
      • 数据层
        • 存储对象 ---> dict ---> Json ---> MySQL
        • MySQL ---> Json ---> dict ---> 获取对象

    ORM

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

    ​ 类名 ---> 表名
    ​ 对象 ---> 一条记录
    ​ 对象.属性 ---> 字段

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

    ​ 创建字段的类型,对应数据表的一个个字段的创建规范

    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=Flase,default=None):
            super().__init__(name,column_type,primary_key,default)
            
            
    #class Father:
    #	def __inti__(self.*arg,**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 = IntegerFild(name='user id')
        user_name = StringField(name='name')  
        pwd = StringField(name='pwd')
        
    class Movie(Models):
        pass
    
    user = User(id='007',name='tank',pwd='123')  #  ---> 一条记录
    # print(user)
    # print(type(user))
    
    movie = Movie(m_id='1',movie_name='json真实写真')
    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__)
    

    问题1: 解决代码冗余的问题,比如有100张表,需要写100次__initial__
    解决1: 继承一个父类,父类中定义一个 __init__

    问题2: 无法预测每一张表中的字段是什么,无法通过父类的__init__解决问题.
    解决2: 通过继承字典,内部的_init_,可以接受"任意个数" 的关键字参数

    问题3: 继承字典的类实例化的对象,无法通过"对象.属性" 的方式存取值
    解决3: 通过__setattr__, __getattr__来实现,让字典对象与普通对象一模一样,并且具备字典原有的特性.

    元类需要处理的问题:

    1. 给数据表类,强制必须要有一个主键
    2. 逐渐必须是唯一的
    
    user_obj = User(user_id = 1,user_name = 'tank',age = 18)
    # insert into User(name,age) values('tank',18);
    user_obj,save()
    
    list1 = []
    
    obj.save() # obj.table_name
    sql = "insert into Movie(name,age,3,4,5...) values('tank',18,3,4,5...)"
    # insert into obj.table_name(name,age,3,4,5...) values('tank',18,3,4,5...);
    
    
    

    创建字段的类型,对应数据表中的一个个字段的创建规范

    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().__inti__(name,column_type,primtary_key,default)
    

    元类需要处理的问题

    	1. 一张表必须要有一个表名
    	2. 给数据表类,强制必须要有一个主键,主键必须是唯一的
    	3. 将数据表中,所有的字段对象,都存在一个独立的字典中
    
    class OrmMtaClass(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 int 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 int 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 __serattr__(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')
        
    # 用户表
    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')
        
        
    if __name__ == '__main__':
        print(User.__dict__)
    
  • 相关阅读:
    python给邮箱发送消息
    shell 的echo和 printf
    shell 基本运算符
    shell傳遞參數
    shell變量和數組
    pycharm的放大和缩小字体的显示 和ubunt的截圖工具使用 ubuntu上安装qq微信等工具
    flask的g对象
    mysqlcilent的安装
    Ubuntu安装 和 python开发
    使用python来建立http服务
  • 原文地址:https://www.cnblogs.com/LZF-190903/p/11795380.html
Copyright © 2020-2023  润新知