一、exec模块的补充

python的内置模块,可以把“字符串形式”的python代码,添加到全局名称空间或局部名称空间中

# 1. 对全局名称空间中的值进行修改
## 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)

# 2. 局部名称空间
## 1. 文本形式的python代码
code = '''
x=100
y=200
def func():
    pass
'''

## 2. 全局名称空间 {}
global_dict={'x':200}

## 3. 局部名称空间 {}
local_dict={}

exec(code,global_dict,local_dict)
print(local_dict)

二、元类

(一)什么是元类

  1. python中一切皆对象,而类本质上也是另一个类实例化出来的对象,而这个类就叫做元类(简称类的类),内置的元类为type
  2. 元类可以控制类的创建

(二)通过class关键字创建类

class创建类时,内部会自动调用元类type,type会帮我们创建一个自定义类,此时会传入三个参数:

  1. 类名class_name
  2. class_bases = (object,)
  3. 类的名称空间class_dic,由执行类体代码得到的

(三)自定义元类控制类的创建

  • 自定义创建元类:

    1. 自定义一个元类,继承type,派生出自己的属性和方法
    2. 通过metaclass指定自定义好的元类,来控制类的创建
  • 通过元类type创建类,会在调用的时候(__call__)做三件事:
    1. 产生一个空对象
    2. 调用__init__方法初始化对象obj
    3. 返回初始化好的obj
class MyMeta(type):
    # 控制对象的创建
    # def __new__(cls,class_name,class_base,class_dic)
    # 控制类的定义
    def __init__(self,class_name,class_base,class_dic):
        # 判断首字母是否大写
        if not class_name.istitle():
            raise TypeError ('类的首字母必须大写')

        # 控制类中必须要有注释
        if not class_dic.get('__doc__'):
            raise TypeError('类内部必须要写注释')

        # 模拟type元类内部做的事情
        def __call__(self,*args,**kwargs):
            # 1. 调用__new__创建一个空对象
            obj = object.__new__(self)

            # 2. 执行__init__(self,*args,**kwargs)
            obj.__init__(*args,**kwargs)
            return obj

class Foo(object,metaclass=MyMeta):
    '''注释'''
    x= 10
    def __init__(self,a,b):
        self.a = a
        self.b = b

    def f1(self):
        print('f1')

foo = Foo(10,20)  # 调用Foo对象,会触发__call__
print(foo.b)

三、ORM

  1. ORM:对象关系映射,将类和数据库中的数据表进行映射

    类名对应表名,对象对应记录,属性对应字段

  2. 这样可以通过对象.属性的方法直接访问到表数据,将数据库的增删改查全部封装成一个个函数

# 1. 字段类
## 1. 父类
class Field:
    def __init__(self,name,type,primary_key,default):
        self.name=  name
        self.type = type
        self.primary_key = primary_key
        self.default= default

## 2. 整形类
class Integer(Field):
    def __init__(self,name,type='int',primary_key=False,default=0):
        super().__init__(name,type,primary_key,default)

## 3. 字符串类
class String(Field):
    def __init__(self,name,type='varchar',primary_key=False,default=None):
        super().__init__(name,type,primary_key,default)

# 2. 元类
class OrmMetaClass(type):
    def __new__(cls, class_name,class_bases,class_dic):
        # 1. Models不用做判断,剔除掉Models类,
        if class_name=='Models':
            return type.__new__(cls,class_name,class_bases,class_dic)

        # 2. 表名、主键、存储字段对象
        table_name = class_dic.get('table_name',class_name)  # 如果没有表名,类名做表名
        primary_key = None
        mappings = {}  # 存储字段对象,防止,表记录对象.属性时触发不了__getattr__

        # 3. 判断是否是唯一主键和必须要有主键,同时筛选出字段对象
        for k,v in class_dic.items():
            if isinstance(v,Field):  # 判断是否是字段对象
                mappings[k] = v  # k是字段名,v是字段对象,v.name=k

                if v.primary_key:  # 如果字段对象中主键为真
                    if primary_key:  # 默认primary_key为空,如果成立,说明,有两个主键
                        raise TypeError('只能有一个主键')
                    primary_key = k  # k = v.name
        # 4. 将类的内存空间中的的字段对象剔除,防止触发不了__getattr__,同时节省内存
        for k in mappings.keys():
            class_dic.pop(k)

        # 5. 如果此时primary_key为空,说明没有主键
        if not primary_key:
            raise TypeError('必须要有一个主键')

        # 6. 将主键名,表名,存储字段对象的字典存入类的名称空间
        class_dic['table_name'] = table_name
        class_dic['primary_key'] = primary_key
        class_dic['mappings'] = mappings

        # 7. 将修改好的名称空间,返回出去给__init__
        return type.__new__(cls,class_name,class_bases,class_dic)

# 3. 表名父类
class Models(dict,metaclass=OrmMetaClass):
    # 1. 对象.属性没有触发,返回字典取值,模仿对象中的属性
    def __getattr__(self, item):
        return self.get(item)

    # 2. 对象.属性=赋值时触发,返回字典增加值,方便后续存储
    def __setattr__(self, key, value):
        self[key] = value

# 4. 用户表类
class User(Models):  # 继承的dict,不需要设置__init__
    user_id = Integer(name = 'user_id',primary_key=True)
    user_name= String(name='user_name')
    pwd = String(name='pwd')

u = User(user_id=1,user_name='wick',pwd='123')
print(u.user_id,u.user_name,u.pwd)

(day38)元类+ORM的更多相关文章

  1. 元类实现ORM

    1. ORM是什么 ORM 是 python编程语言后端web框架 Django的核心思想,"Object Relational Mapping",即对象-关系映射,简称ORM. ...

  2. 使用元类 编写ORM

    元类 一句话: 元类定制类的创建行为 知识点 1.类的创建: python这种动态语言,函数和类的定义,不是编译时定义的,而是运行时动态创建的. Python解释器遇到class定义时,仅仅是扫描一下 ...

  3. python——type()、metaclass元类和精简ORM框架

    1.type()函数 if __name__ == '__main__': h = hello() h.hello() print(type(hello)) print(type(h)) Hello, ...

  4. 谈谈Python中元类Metaclass(二):ORM实践

    什么是ORM? ORM的英文全称是“Object Relational Mapping”,即对象-关系映射,从字面上直接理解,就是把“关系”给“对象”化. 对应到数据库,我们知道关系数据库(例如Mys ...

  5. python ORM理解、元类

    元类 参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143191 ...

  6. 04 -- 元类和ORM

    本篇主要介绍元类,为什么说一切皆对象:如何动态的创建类等:以及ORM,即什么是ORM等知识 一.元类 1.1 在Python中一切皆对象 在学习元类中我们首先需要了解一个概念-- python中一切皆 ...

  7. Python元类实战,通过元类实现数据库ORM框架

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第19篇文章,我们一起来用元类实现一个简易的ORM数据库框架. 本文主要是受到了廖雪峰老师Python3入门教程的启 ...

  8. python-元类和使用元类实现简单的ORM

    元类 面向对象中,对象是类的实例,即对象是通过类创建出来的,在python中,一切皆对象,同样,类也是一个对象,叫做类对象,只是这个类对象拥有创建其子对象(实例对象)的能力.既然类是对象,那么类是通过 ...

  9. 元类、orm

    目录 一.内置函数exec 二.元类 1. 什么是元类 2. 元类的作用 3. 创建类的两种方法 4. 怎么自定义创建元类 三.ORM 1. ORM中可能会遇到的问题 2. ORM中元类需要解决的问题 ...

随机推荐

  1. vue2.x 监听数据变化 ---- watch

    computed: { //需要监听的数据 loginToken () { return this.$store.state.userinfo.status; } }, watch: { loginT ...

  2. SpringCloud微服务常见组件理解

    概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很多原理,很多人可能并不知晓 ...

  3. nexus搭建maven仓库管理

    Linux搭建nexus仓库 1.安装jdk 1.1 获取安装包,解压到指定目录: 1 tar xf jdk.tar.gz -C /opt/export 1.2 配置环境变量: 1 # vim /et ...

  4. resharper 8.2

    用户名:ronle注册码:ZoJzmeVBoAv9Sskw76emgksMMFiLn4NM

  5. kudu 查看元数据信息

    package com.lala.lala.pipe.dbinfo import org.apache.kudu.client.KuduClient import com.lala.lala.comm ...

  6. $.Ajax、$.Get、$.Post代码实例参数解析

    $.ajax 语法: $.ajax({name:value, name:value, ... }) 示例: $.ajax({ url: "/testJson", type: &qu ...

  7. 简单ALV得演示(用到了ALV可编辑及保存后修改数据库)

    *&---------------------------------------------------------------------* *& Report YPMRP010_ ...

  8. px与em的区别

    PX特点:px像素(Pixel).相对长度单位.像素px是相对于显示器屏幕分辨率而言的.EM特点 1. em的值并不是固定的:2. em会继承父级元素的字体大小.

  9. maven-dependencies插件的模拟实现

    maven-dependencies插件的作用就是从本地的maven仓库中提取jar包,放到某个文件夹下面.这个功能其实是很简单的. 我在一家银行工作时,公司电脑都无法连外网,所以无法通过maven下 ...

  10. spring cloud 框架源码 activiti工作流 vue.js html 跨域 前后分离 springboot

    1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...