python——type()、metaclass元类和精简ORM框架
1、type()函数
if __name__ == '__main__':
h = hello()
h.hello()
print(type(hello))
print(type(h))
Hello, world.
<class 'type'>
<class '__main__.Hello'>
2、metaclass元类
#metaclass 元类 metaclass允许你创建类或者修改类
class Listmetaclass(type):
def __new__(cls, name,bases,attrs):
attrs['add'] = lambda self,value:self.append(value) #增加了add()方法
return type.__new__(cls,name,bases,attrs)
class MyList(list,metaclass=Listmetaclass):
pass
#__new__()方法接收到的参数依次是: #1、当前准备创建的类的对象;
#2、类的名字;
#3、类继承的父类集合;
#4、类的方法集合。 #元类一般情况不常用,但总会遇到需要通过metaclass修改类定义的。ORM就是一个典型的例子。
#ORM全称“Object Relational Mapping”,即对象-关系映射,就是把关系数据库的一行映射为一个对象,
# 也就是一个类对应一个表,这样,写代码更简单,不用直接操作SQL语句。
#要编写一个ORM框架,所有的类都只能动态定义,因为只有使用者才能根据表的结构定义出对应的类来。
3、精简ORM框架
#开始编写ORM框架
class Field(object):
def __init__(self,name,column_type):
self.name = name
self.column_type = column_type
def __str__(self):
return '<%s:%s>'%(self.__class__.__name__,self.name) class StringField(Field):
def __init__(self,name):
super(StringField,self).__init__(name,'varchar(100)') class IntegerField(Field):
def __init__(self,name):
super(IntegerField,self).__init__(name,'bigint')
#下一步,就是编写最复杂的ModelMetaclass了:
class ModelMetaclass(type):
def __new__(cls, name,bases,attrs):
if name == 'Model': #排除掉对Model类的修改;
return type.__new__(cls,name,bases,attrs)
print('Found Model: %s'%name)
mappings = dict()
for k,v in attrs.items(): #查找定义的类的所有属性,
if isinstance(v,Field): #如果找到一个Field属性,
print('Found mapping: %s ==> %s' % (k, v))
mappings[k] = v #就把它保存到一个__mappings__的dict中
for k in mappings.keys():
attrs.pop(k) #同时从类属性中删除该Field属性,否则,容易造成运行时错误(实例的属性会遮盖类的同名属性);
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致 把表名保存到__table__中
return type.__new__(cls,name,bases,attrs) #基类Model
class Model(dict,metaclass=ModelMetaclass):
def __init__(self,**kw):
super(Model,self).__init__(**kw)
def __getattr__(self, item): #没有找到的属性,就在这里找
try:
return self[item]
except KeyError:
raise AttributeError(r"'Model' object has no attrs :'%s'"%item) def __setattr__(self, key, value):
self[key] = value def save(self):
fields = []
params = []
args = []
for k,v in self.__mappings__.items():
fields.append(v.name)
params.append('?')
args.append(getattr(self,k,None))
sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args)) #子类User
# 定义类的属性到列的映射:
class User(Model):
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password')
age = IntegerField('age') #开始编写ORM框架
class Field(object):
def __init__(self,name,column_type):
self.name = name
self.column_type = column_type
def __str__(self):
return '<%s:%s>'%(self.__class__.__name__,self.name) class StringField(Field):
def __init__(self,name):
super(StringField,self).__init__(name,'varchar(100)') class IntegerField(Field):
def __init__(self,name):
super(IntegerField,self).__init__(name,'bigint')
#下一步,就是编写最复杂的ModelMetaclass了:
class ModelMetaclass(type):
def __new__(cls, name,bases,attrs):
if name == 'Model': #排除掉对Model类的修改;
return type.__new__(cls,name,bases,attrs)
print('Found Model: %s'%name)
mappings = dict()
for k,v in attrs.items(): #查找定义的类的所有属性,
if isinstance(v,Field): #如果找到一个Field属性,
print('Found mapping: %s ==> %s' % (k, v))
mappings[k] = v #就把它保存到一个__mappings__的dict中
for k in mappings.keys():
attrs.pop(k) #同时从类属性中删除该Field属性,否则,容易造成运行时错误(实例的属性会遮盖类的同名属性);
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致 把表名保存到__table__中
return type.__new__(cls,name,bases,attrs) #基类Model
class Model(dict,metaclass=ModelMetaclass):
def __init__(self,**kw):
super(Model,self).__init__(**kw)
def __getattr__(self, item): #没有找到的属性,就在这里找
try:
return self[item]
except KeyError:
raise AttributeError(r"'Model' object has no attrs :'%s'"%item) def __setattr__(self, key, value):
self[key] = value def save(self):
fields = []
params = []
args = []
for k,v in self.__mappings__.items():
fields.append(v.name)
params.append('?')
args.append(getattr(self,k,None))
sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params))
print('SQL: %s' % sql)
print('ARGS: %s' % str(args)) #子类User
# 定义类的属性到列的映射:
class User(Model):
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password')
age = IntegerField('age')
当用户定义一个class User(Model)
时,Python解释器首先在当前类User
的定义中查找metaclass
,如果没有找到,就继续在父类Model
中查找metaclass
,找到了,就使用Model
中定义的metaclass
的ModelMetaclass
来创建User
类,也就是说,metaclass可以隐式地继承到子类,但子类自己却感觉不到。
在ModelMetaclass
中,一共做了几件事情:
排除掉对
Model
类的修改;在当前类(比如
User
)中查找定义的类的所有属性,如果找到一个Field属性,就把它保存到一个__mappings__
的dict中,同时从类属性中删除该Field属性,否则,容易造成运行时错误(实例的属性会遮盖类的同名属性);把表名保存到
__table__
中,这里简化为表名默认为类名。
在Model
类中,就可以定义各种操作数据库的方法,比如save()
,delete()
,find()
,update
等等。
我们实现了save()
方法,把一个实例保存到数据库中。因为有表名,属性到字段的映射和属性值的集合,就可以构造出INSERT
语句。
编写代码试试:
if __name__ == '__main__':
u = User(id = 12345,name = 'john',email = '123456789@qq.com',password = '666666')
u.age = 12
u.save()
Found Model: User
Found mapping: id ==> <IntegerField:id>
Found mapping: name ==> <StringField:username>
Found mapping: email ==> <StringField:email>
Found mapping: password ==> <StringField:password>
Found mapping: age ==> <IntegerField:age>
SQL: insert into User (id,username,email,password,age) values (?,?,?,?,?)
ARGS: [12345, 'john', '123456789@qq.com', '666666', 12]
即User类中做好了到列的映射的类属性,都能添加到sql语句中,而未做好了到列的映射的类属性:如height,则会过滤掉,实现数据库列的字段的高度可定制
save()
方法已经打印出了可执行的SQL语句,以及参数列表,只需要真正连接到数据库,执行该SQL语句,就可以完成真正的功能。下面入库操作,还有剩下的删改查操作可自行解决。python——type()、metaclass元类和精简ORM框架的更多相关文章
- Python元类实战,通过元类实现数据库ORM框架
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Python专题的第19篇文章,我们一起来用元类实现一个简易的ORM数据库框架. 本文主要是受到了廖雪峰老师Python3入门教程的启 ...
- [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式
使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...
- 深刻理解Python中的元类(metaclass)以及元类实现单例模式
在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍 ...
- Python中的元类(metaclass)
推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...
- Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法
Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...
- python基础——使用元类
python基础——使用元类 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello. ...
- Python 中的元类到底是什么?这篇恐怕是最清楚的了
类作为对象 在理解元类之前,您需要掌握 Python 的类.Python 从 Smalltalk 语言中借用了一个非常特殊的类概念. 在大多数语言中,类只是描述如何产生对象的代码段.在 Python ...
- Python基础:元类
一.概述 二.经典阐述 三.核心总结 1.类的创建过程 2.元类的使用惯例 四.简单案例 1.默认行为 2.使用元类 五.实践为王 一.概述 Python虽然是多范式的编程语言,但它的数据模型却是 纯 ...
- python中面向对象元类的自定义用法
面向对象中的常用方法 1.instance 和 issubclass instance :判断两个对象是不是一类 issubclass :判断某个类是不是另一个类的子类 #两个常用方法的使用 clas ...
随机推荐
- Scrum Meeting 10.24
成员 已完成任务 下一阶段任务 用时 徐越 阅读后端代码,了解服务器的概念,以及服务器和终端间的通信机制 学习服务器配置 4h 赵庶宏 阅读后端代码,了解服务器的概念,以及服务器和终端间的通信机制 阅 ...
- 如何知道一个App的包名呢
包名(Package name)是Android系统中判断一个APP的唯一标识 记录我获取包名的几种方式 方法一:通过cmd命令,打开你要获取包名的APP 1.adb shell 2.dumpsys ...
- Java第二天——标识符命名规则、Java的知识、快捷键的使用、Scanner获取值的常用方法
1.标识符命名规则 字母.下划线.数字.美元符号($)由这四个部分组成. 标识符=首字母+其他 首字母:字母.下划线.美元符号($) 其他:字母.下划线.数字.美元符号($) 注意: 1.首字母不能为 ...
- PBS命令和使用
PBS是公开源代码的作业管理系统,在此环境下运行,用户不需要指定程序在哪些节点上运行,程序所需的硬件资源由PBS管理和分配. PBS(Portable Batch System)是由NASA开发的灵活 ...
- [转帖]InfiniBand 主流厂商 和 产品分析
InfiniBand 主流厂商 和 产品分析 Mellanox成立于1999年,总部设在美国加州和以色列,Mellanox公司是服务器和存储端到端连接InfiniBand解决方案的领先供应商.20 ...
- intel 的架构图
第一代: 第二代 第三代 以及对比
- 关于Delphi内存表的使用说明
关于Delphi内存表的使用说明: 1.建立临时表 数据输入是开发数据库程序的必然环节.在Client/Server结构中,客户端可能要输入一批数据后,再向服务器的后台数据库提交,这就需要在本地(客 ...
- C++模式学习------策略模式
当遇到同一个对象有不同的行为,方法,为管理这些方法可使用策略模式. 策略模式就是对算法进行包装,是把使用算法的责任和算法本身分割开来.通常把一个系列的算法包装到一系列的策略类里面,这些类继承一个抽象的 ...
- DAY7-Python学习笔记
前记: 这几天在弄小程序,view页面的开发很简单,但是在加载图片上遇到了问题,小程序的大小不能超过2M,所以大部分的图片内容要通过request请求服务器来获取,这里之前学习小程序的时候是通过网站A ...
- STL 容器的概念
STL 容器的概念 在实际的开发过程中,数据结构本身的重要性不会逊于操作于数据结构的算法的重要性,当程序中存在着对时间要求很高的部分时,数据结构的选择就显得更加重要. 经典的数据结构数量有限,但是我们 ...