(day38)元类+ORM
一、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)
二、元类
(一)什么是元类
- python中一切皆对象,而类本质上也是另一个类实例化出来的对象,而这个类就叫做元类(简称类的类),内置的元类为type
- 元类可以控制类的创建
(二)通过class关键字创建类
class创建类时,内部会自动调用元类type,type会帮我们创建一个自定义类,此时会传入三个参数:
- 类名class_name
- class_bases = (object,)
- 类的名称空间class_dic,由执行类体代码得到的
(三)自定义元类控制类的创建
- 自定义创建元类:
- 自定义一个元类,继承type,派生出自己的属性和方法
- 通过metaclass指定自定义好的元类,来控制类的创建
- 通过元类type创建类,会在调用的时候(
__call__)做三件事:- 产生一个空对象
- 调用
__init__方法初始化对象obj - 返回初始化好的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
ORM:对象关系映射,将类和数据库中的数据表进行映射
类名对应表名,对象对应记录,属性对应字段
这样可以通过对象.属性的方法直接访问到表数据,将数据库的增删改查全部封装成一个个函数
# 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的更多相关文章
- 元类实现ORM
1. ORM是什么 ORM 是 python编程语言后端web框架 Django的核心思想,"Object Relational Mapping",即对象-关系映射,简称ORM. ...
- 使用元类 编写ORM
元类 一句话: 元类定制类的创建行为 知识点 1.类的创建: python这种动态语言,函数和类的定义,不是编译时定义的,而是运行时动态创建的. Python解释器遇到class定义时,仅仅是扫描一下 ...
- python——type()、metaclass元类和精简ORM框架
1.type()函数 if __name__ == '__main__': h = hello() h.hello() print(type(hello)) print(type(h)) Hello, ...
- 谈谈Python中元类Metaclass(二):ORM实践
什么是ORM? ORM的英文全称是“Object Relational Mapping”,即对象-关系映射,从字面上直接理解,就是把“关系”给“对象”化. 对应到数据库,我们知道关系数据库(例如Mys ...
- python ORM理解、元类
元类 参考链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143191 ...
- 04 -- 元类和ORM
本篇主要介绍元类,为什么说一切皆对象:如何动态的创建类等:以及ORM,即什么是ORM等知识 一.元类 1.1 在Python中一切皆对象 在学习元类中我们首先需要了解一个概念-- python中一切皆 ...
- Python元类实战,通过元类实现数据库ORM框架
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第19篇文章,我们一起来用元类实现一个简易的ORM数据库框架. 本文主要是受到了廖雪峰老师Python3入门教程的启 ...
- python-元类和使用元类实现简单的ORM
元类 面向对象中,对象是类的实例,即对象是通过类创建出来的,在python中,一切皆对象,同样,类也是一个对象,叫做类对象,只是这个类对象拥有创建其子对象(实例对象)的能力.既然类是对象,那么类是通过 ...
- 元类、orm
目录 一.内置函数exec 二.元类 1. 什么是元类 2. 元类的作用 3. 创建类的两种方法 4. 怎么自定义创建元类 三.ORM 1. ORM中可能会遇到的问题 2. ORM中元类需要解决的问题 ...
随机推荐
- 二分法查找(C语言)
二分法是一种高效的查找方法,其适用于已经排好序的数组 基本思路 从数组最中间的数开始查找判断,若不是需要查找的数字,则比较大小,之后则在从中间分开的两边中的一边从最中间开始查找判断,以此类推 算法描述 ...
- Vue 使用comouted计算属性
computed计算属性 使用方法见代码: <!doctype html> <html lang="en"> <head> <meta c ...
- pycharm配置docker
- Luogu P5022 旅行
开始写复赛题了 先放张图纪念我惨烈的卡常之路 不说了,简直悲伤 题目链接 思路么..不想写了 Code //不要在意四十行超级加速,卡常用的 #include<bits/stdc++.h> ...
- 解决静态方法调用注入的service
在使用jpa的复杂查询时,声明了specification时声明为静态方法,导致注入的service无法使用,故想到俩种方式,一种手动注入,一种注解注入,此文使用的时注解注入: 解决静态方法调用注入的 ...
- logical函数
logical函数(逻辑函数) logical(x):x ~=0时,logical(x)=1:x = 0时,logical(x)=0
- java为什么要用类型擦除实现泛型?--c++,java,c# 的泛型是如何实现的
所以总结一下c++,java,c#的泛型.c++的泛型在编译时完全展开,类型精度高,共享代码差.java的泛型使用类型擦出,仅在编译时做类型检查,在运行时擦出,共享代码好,但是类型精度不行.c#的泛型 ...
- 【机器学习】PCA
目录 PCA 1. PCA最大可分性的思想 2. 基变换(线性变换) 3. 方差 4. 协方差 5. 协方差矩阵 6. 协方差矩阵对角化 7. PCA算法流程 8. PCA算法总结 PCA PCA 就 ...
- linux 如何指定nologin用户执行命令
在linux中建立网站时,我们一般分配一个www之类的用户给网站应用程序. 如果我们使用root或者具有管理员权限的账号在网站目录下去创建文件时,会遇到各种权限问题. 这时我们可以切换到www用户,这 ...
- JDK1.8新特性——Stream API
JDK1.8新特性——Stream API 摘要:本文主要学习了JDK1.8的新特性中有关Stream API的使用. 部分内容来自以下博客: https://blog.csdn.net/icarus ...