一、内置函数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. 创建类的两种方法

  1. 通过class关键字创建类,内部会自动调用type(),type帮我们创建一个自定义类。
  2. 通过手动调用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. 怎么自定义创建元类

  1. 自定义一个元类,需要继承type,可以派生出自己的属性与方法。

  2. 如果想要给类指定元类,可以使用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. 问题1: 解决代码荣誉问题,比如有100张表,需要写100次__init__。
  • 解决1: 继承一个父类,父类中定义一个__init__。
  1. 问题2: 无法预测每一张表中的字段是什么,无法通过父类的__init__解决问题。
  • 解决2: 通过继承字典,内部的__init__, 可以接受“任意个数”的“关键字参数”。
  1. 问题3: 继承字典的类实例化的对象,无法通过“对象.属性”的方式存取值。
  • 解决3: 通过__setattr__,__getattr__来实现,让字典对象与普通对象一模一样,并且具备字典原有的特性。

2. ORM中元类需要解决的问题

  1. 一张表必须要有一个表名

  2. 给数据表类,强制必须要有一个主键,而且主键必须是唯一的。

  3. 将数据表中 所有的字段对象,都存放在一个独立的字典中。

    (存不是目的,目的是为了取值方便)

# 创建字段的类型,对应数据表中的一个个字段的创建规范
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的更多相关文章

  1. (day38)元类+ORM

    目录 一.exec模块的补充 二.元类 (一)什么是元类 (二)通过class关键字创建类 (三)自定义元类控制类的创建 三.ORM 一.exec模块的补充 python的内置模块,可以把" ...

  2. 元类实现ORM

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

  3. 使用元类 编写ORM

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

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

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

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

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

  6. python ORM理解、元类

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

  7. 04 -- 元类和ORM

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

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

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

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

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

随机推荐

  1. Yarn参数优化(Fair Scheduler版本)

    YARN 自从hadoop2.0之后, 我们可以使用apache yarn 来对集群资源进行管理.yarn把可以把资源(内存,CPU)以Container的方式进行划分隔离.YARN会管理集群中所有机 ...

  2. Codeforces Round #677 (Div. 3)【ABCDE】

    比赛链接:https://codeforces.com/contest/1433 A. Boring Apartments 题解 模拟即可. 代码 #include <bits/stdc++.h ...

  3. BZOJ1396 识别子串【SAM+SegmentTree】

    BZOJ1396 识别子串 给定一个串\(s\),对于串中的每个位置,输出经过这个位置且只在\(s\)中出现一次的子串的最短长度 朴素的想法是,我们要找到那些只出现一次的子串,之后遍历每个串,把串所覆 ...

  4. HDU2065 "红色病毒"问题 【组合数学 二项式定理】

    HDU2065 "红色病毒"问题 Description: 医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色 ...

  5. 【uva 1395】Slim Span(图论--最小生成树+结构体快速赋值 模版题)

    题意:给一个N(N<=100)个点的联通图(无自环和平行边),求苗条度(最大边-最小边的值)尽量小的生成树. 解法:枚举+Kruskal.先从小到大排序边,枚举选择的最小的边. 1 #inclu ...

  6. Codeforces Round #687 (Div. 2, based on Technocup 2021 Elimination Round 2) B. Repainting Street (枚举)

    题意:有\(n\)栋房子,每栋房子都有自己的颜色\(c_i\),你每次可以对连续的长度为\(k\)的区间改变任何房子的颜色,问最少多少次可以使得所有房子颜色相同. 题解:因为只有\(100\)中颜色, ...

  7. 添加特定软件证书到windows不信任列表

    $target="C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" $filePath=$PSScript ...

  8. centos 7下安装配置Supervisor

    1.安装Supervisor centos下安装yum install supervisor 2. systemctl enable supervisord 开机自启 systemctl start ...

  9. Xtrabackup 物理备份

    目录 Xtrabackup 安装 Xtrabackup 备份介绍 Xtrabackup全量备份 准备备份目录 全量备份 查看全量备份内容 Xtrabackup 全量备份恢复数据 删除所有数据库 停止数 ...

  10. C++ part7

    1.C++ 继承和组合 类的组合和继承一样,是复用的重要方式. 要优先使用组合而不是继承. 原因: 组合是黑箱复用,对局部类的内部细节不可见:继承是白箱复用,父类的内部细节可见,破坏封装性. 继承在编 ...