zoukankan      html  css  js  c++  java
  • day38 元类

    exec模块

    是什么

    exec是一个python内置模块

    exec的作用

    '''
    x=10
    def func1():
    	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)#{'x': 10
    print(local_dict)#{'y': 20}
    

    元类

    什么是元类

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

    元类的作用

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

    ​ 元类可以帮我们控制类的调用

    怎么自定义创建元类

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

    2)给需要使用的类,通过metaclass指定自定义好的元类

    ​ —class Chinesse(metaclass='自定义的元类')

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

    orm

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

    类名---》表名

    对象---》一条记录

    对象.属性---》字段

    模拟Django的orm,为了将数据库的增删改查全部封装成一个个的方法,比如sava,delete,update,select

    字段类

    #1.创建字段的类型,对应数据表中的一个个字段的创建规范
    class Field:
        def __init__(self,name,colum_type,primary_key,default):
            self.name=name
            self.colum_type=colum_type
            self.primary_key=primary_key
            self.default=default
    
    #Integer
    class IntegerField(Field):
        def __init__(self,name,colum_type='int',primary_key=False,default=0):
            super().__init__(name,colum_type,primary_key,default)
    
    #String
    class StringField(Field):
        def __init__(self, name, colum_type='varchar(64)', primary_key=False, default=None):
            super().__init__(name, colum_type, primary_key, default)
    

    元类

    
    '''
    元类需要处理的问题:
        1.一张表必须要有一个表名。
        2.给数据表类,强制必须要有一个主键,主键必须是唯一的。
        3.将数据表中,所有的字段对象,都存放在一个独立的字典中
            存不是目的,目的是为了取值方便。
    '''
    class OrmMetaClass(type):
        def __new__(cls,class_name,class_base,class_dict):
            # print(class_name)
            #过滤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)
    
            #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)
    

    Models类

    '''
    问题1: 解决代码荣誉问题,比如有100张表,需要写100次__init__。
    解决1: 继承一个父类,父类中定义一个__init__。
    
    问题2: 无法预测每一张表中的字段是什么,无法通过父类的__init__解决问题。
    解决2: 通过继承字典,内部的__init__, 可以接受“任意个数”的“关键字参数”。
    
    问题3: 继承字典的类实例化的对象,无法通过“对象.属性”的方式存取值。
    解决3: 通过__setattr__,__getattr__来实现,让字典对象与普通对象一模一样,并且具备字典原有的特性。
    
    '''
    class Models(dict,metaclass=OrmMetaClass):
        #会在 对象.属性 没有时触发
        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',primary_key=True)
        user_name=StringField(name='name')
        pwd=StringField(name='pwd')
    
    #电影表类
    class Movie(Models):
        # 强调:最好与字段类型的name属性同名
        user_id = IntegerField(name='user_id',primary_key=True)
        user_name = StringField(name='name')
        pwd = StringField(name='pwd')
    
  • 相关阅读:
    [自娱自乐] 2、超声波测距模块DIY笔记(二)
    [自制简单操作系统] 9、命令行与应用程序 整体回顾
    [汇编] C语言中嵌入汇编
    [Java Web] 5、JSP (1) 注释 & Scriptlet
    [自娱自乐] 1、超声波测距模块DIY笔记(一)
    [Java Web] 4、JavaScript 简单例子(高手略过)
    [C#] Timer + Graphics To Get Simple Animation (简单的源码例子,适合初学者)
    [自制简单操作系统] 8、多任务(三)——多窗口与优先级
    [自制简单操作系统] 7、多任务(二)——任务管理自动化&任务休眠
    [自制简单操作系统] 6、多任务(一)
  • 原文地址:https://www.cnblogs.com/zqfzqf/p/11795350.html
Copyright © 2011-2022 走看看