元类、orm
一、内置函数exec
作用:
在全局变量和局部变量上下文中执行给定的源。源可以是表示一个或多个Python语句的字符串,也可以是compile()返回的代码对象。全局变量必须是字典,局部变量可以是任何映射,默认为当前全局变量和局部变量。如果只提供全局变量,则局部变量默认为全局变量。
语法:
# 局部名称空间
# 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)
二、元类
1. 什么是元类
我们都知道在python中一切皆对象,其实python中的类也是一种类对象。既然是对象,那肯定是实例化出来的。因此,我们把可以实例化出类的类叫做元类。在Python中,元类即为type,type是所有类对象的类。
2. 元类的作用
元类可以帮我们控制类的创造。
3. 创建类的两种方法
- 通过class关键字创建类,内部会自动调用type(),type帮我们创建一个自定义类。
- 通过手动调用type()实例化得到自定义的类。
# 方法1
class Chinese:
country = 'China'
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print('speak Chinese...')
p1 = Chinese('tank', 18)
print(Chinese)
print(p1)
print(type(p1)) # Chinese
print(type(Chinese)) # <class 'type'>
# 方法2
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)
Chinese = type(class_name, class_base, class_dict)
print(Chinese)
4. 怎么自定义创建元类
自定义一个元类,需要继承type,可以派生出自己的属性与方法。
如果想要给类指定元类,可以使用metaclass指定一个自定义元类。
# 语法:
class func(metaclass=自定义元类):
# 自定义一个子元类
class MyMeta(type):
# 子类的方法与父类的方法一样,先用子类的,子类覆盖父类的__init__方法。
# 控制了类的定义
def __init__(self, class_name, class_base, class_dict):
# class_name为MyMeta实例化出来的对象的对象名,
# class_base为MyMeta实例化出来的对象的父类名,
# class_dict为MyMeta实例化出来的对象的名称空间。
print(class_name)
print(class_base)
print(class_dict)
super().__init__(class_name, class_base, class_dict)
# metaclass ---> 自定义的元类
# 因为Foo类只是由元类实例化出来的一个类对象,它还可以继承一个父类object
class Foo(object,metaclass=MyMeta): # MyMeta(Foo,(object, ),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__
三、ORM
Object Relational Mapping,意为对象关系映射,可以将一个对象映射到MySQL中的数据表,使类和表一一对应。
类名 ---> 表名
一个对象 ---> 一条记录
对象.属性 ---> 字段
1. ORM中可能会遇到的问题
- 问题1: 解决代码荣誉问题,比如有100张表,需要写100次__init__。
- 解决1: 继承一个父类,父类中定义一个__init__。
- 问题2: 无法预测每一张表中的字段是什么,无法通过父类的__init__解决问题。
- 解决2: 通过继承字典,内部的__init__, 可以接受“任意个数”的“关键字参数”。
- 问题3: 继承字典的类实例化的对象,无法通过“对象.属性”的方式存取值。
- 解决3: 通过__setattr__,__getattr__来实现,让字典对象与普通对象一模一样,并且具备字典原有的特性。
2. ORM中元类需要解决的问题
一张表必须要有一个表名
给数据表类,强制必须要有一个主键,而且主键必须是唯一的。
将数据表中 所有的字段对象,都存放在一个独立的字典中。
(存不是目的,目的是为了取值方便)
# 创建字段的类型,对应数据表中的一个个字段的创建规范
class Field:
# 每个字段都会有字段名,列类型,是否为主键,默认值 这些属性
def __init__(self,field_name,column_type,primary_key,default):
self.field_name = field_name
self.column_type = column_type
self.primary_key = primary_key
self.default = default
# 整形integer字段
class IntegerField(Field):
def __init__(self,field_name,column_type='int',primary_key=False,default=0):
super().__init__(field_name,column_type,primary_key,default)
# 字符串string字段
class StringField(Field):
def __init__(self,field_name,column_type='varchar(32)',primary_key=False,default=''):
super().__init__(field_name,column_type,primary_key,default)
# 设置自定义元类,满足定义类时的一些需求
class OrmMetaClass(type):
def __new__(cls, class_name, class_base,class_dict):
print(1,class_dict)
# 过滤Models类
if class_name == 'Models':
return type.__new__(cls, class_name, class_base,class_dict)
# 表名
table_name = class_dict.get('table_name',class_name)
# 主键名
primary_key = None
# 定义一个空字典,专门用来存放字段对象
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值是否为true
# 判断主键是否已存在
if primary_key:
raise TypeError('只能有一个主键!')
# 若主键不存在,则给初始的primary_key赋值
primary_key = value.field_name
# 判断是否有一个主键
if not primary_key:
raise TypeError('请设置一个主键!')
print(2, class_dict)
# 给类的名称空间添加表名
class_dict['table_name'] = table_name
# 给类的名称空间添加主键名
class_dict['primary_key'] = primary_key
# 给类的名称空间添加mappings字典
class_dict['mappings'] = mappings
# 资源节省,剔除名称空间内重复的属性
for key in mappings.keys():
class_dict.pop(key)
print(3, class_dict)
# 元类限制结束,返回一个类
return type.__new__(cls, class_name, class_base,class_dict)
# 无法预测每一张表中有哪些字段,通过继承字典,可以接受“任意个数”的“关键字参数”
class Models(dict,metaclass=OrmMetaClass):
# 在通过 对象.属性 试图获取一个不存在的属性时触发
def __getattr__(self, item):
# 正常情况下,字典对象.属性 是无法取得一个值的(none),
# 但是通过__getattr__方法可以使 对象.属性 返回一个值
# 从而让字典对象看起来像一个普通的对象,可以用 对象.属性 的方法取值
return self.get(item)
# 在进行设置属性(赋值:对象.属性 = 属性)操作时触发
def __setattr__(self, key, value):
# 因为self(Models)是一个字典,所以可以用下面的方式进行添加值
# 从而可以使一个字典对象可以通过 对象.属性=属性值 的方式赋值
self[key] = value
# 用户表(一个类就是一张表)
class User(Models):
# 每个属性就是一个字段
user_id = IntegerField(field_name='user_id',primary_key=True)
user_name = StringField(field_name='user_name')
user_pwd = StringField(field_name='pwd')
# 电影表
class Movie(Models):
movie_id = IntegerField(field_name='movie_id',primary_key=True)
movie_name = StringField(field_name='movie_name')
if __name__ == '__main__':
print(4,User.__dict__)
元类、orm的更多相关文章
- (day38)元类+ORM
目录 一.exec模块的补充 二.元类 (一)什么是元类 (二)通过class关键字创建类 (三)自定义元类控制类的创建 三.ORM 一.exec模块的补充 python的内置模块,可以把" ...
- 元类实现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中,一切皆对象,同样,类也是一个对象,叫做类对象,只是这个类对象拥有创建其子对象(实例对象)的能力.既然类是对象,那么类是通过 ...
随机推荐
- 腾讯云TcaplusDB获新加坡MTCS最高等级安全认证
近日,经过国际权威认证机构DNV GL的全面评估审核,TcaplusDB获得了新加坡多层云安全(以下简称"MTCS")T3级最高等级认证,这标志着TcaplusDB全面满足了新加坡 ...
- 校招有感:计算机专业毕业生如何找工作(Java方向)
这两年毕业生的就业形势,大家都看在眼里.由于我平时本职会到校园去做校招,兼职会做培训,所以也接触到了不少计算机应届毕业生. 我看到的计算机专业毕业生,各种情况的都有.虽然其中有学校的因素,但学校的因素 ...
- 深入浅出Java线程池:源码篇
前言 在上一篇文章深入浅出Java线程池:理论篇中,已经介绍了什么是线程池以及基本的使用.(本来写作的思路是使用篇,但经网友建议后,感觉改为理论篇会更加合适).本文则深入线程池的源码,主要是介绍Thr ...
- VS CODE远程办公篇一
作者:良知犹存 转载授权以及围观:欢迎添加微信:becom_me 总述 因为疫情的来临,让远程办公变得原来越火.这次我也是盯上了这个功能,实现在家里远程配置电脑. 嵌入式Linux开发的程序员 ...
- mybatis Sql语句配置详解
sql语句配置 id sqlSession执行的唯一标识 resultMap 结果集封装映射,可用于内部对象一对多封装 resultType 返回的结果类型,直接就是一个po对象 resultSets ...
- Codeforces Round #547 (Div. 3) D. Colored Boots (贪心,模拟)
题意:有两个字符串,两个字符串中的相同字符可以相互匹配,\(?\)可以和任意字符匹配,输出最大匹配的字符数量和它们分别两个字符串中的位置. 题解:很容易贪心,我们先遍历第一个字符串,然后在第二个字符串 ...
- Codeforces Round #669 (Div. 2) C. Chocolate Bunny (交互,构造)
题意:有一个长度为\(n\)的隐藏序列,你最多可以询问\(2n\)次,每次可以询问\(i\)和\(j\)位置上\(p[i]\ mod\ p[j]\)的结果,询问的格式是\(?\ x\ y\),如果已经 ...
- .Net Core 国际化
创建项目什么的就不说了吧 直接进入正题吧 我这里建的是个webapi 添加资源文件 1.首先我们创建一个Language文件夹,这就是我们在后面Startup类中需要配置的目录名. 2.然后我们在La ...
- 【论文笔记】AutoML for MCA on Mobile Devices——论文解读与代码解析
理论部分 方法介绍 本节将详细介绍AMC的算法流程.AMC旨在自动地找出每层的冗余参数. AMC训练一个强化学习的策略,对每个卷积层会给出其action(即压缩率),然后根据压缩率进行裁枝.裁枝后,A ...
- VScode 相关
1.F5运行py文件,打开terminal终端的时候总是弹出Powershell窗口,只能在powershell窗口中用命令行运行程序,实在很不方便. 解法:右键Powershell属性,取消使用旧版 ...