通过ORM模型看python对象创建过程
简易django ORM模型如下所示:
#!/usr/bin/env python
# encoding: utf-8
"""
@version: 1.0
@author: Pis
@license: Apache Licence
@software: PyCharm
@file: orm_test.py
@time: 2018/5/9 9:52
""" #1
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) #2
class StringField(Field):
def __init__(self, name):
super(StringField, self).__init__(name, 'varchar(100)') #3
class IntegerField(Field):
def __init__(self, name):
super(IntegerField, self).__init__(name, 'bigint') #4
# 下一步,就是编写最复杂的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) #5
# 基类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
#6
# 定义类的属性到列的映射:
class User(Model):
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password')
age = IntegerField('age')
#7
if __name__ == "__main__":
u = User(id=12345, name='john', email='123456789@qq.com', password='666666', height="top")
u.age = 12
u.save()
在代码执行过程中,在执行#7之前,首先是class的创建,在没有标明metaclass的情况下默认是由type通过__new__创建class对象,在标明了metaclass的情况下由metaclass的__new__方法创建(关于metaclass 的查找顺序上一篇给出【self,parents,local】),class创建完毕后才开始#7的执行,由于User类没有构造__new__和__init__方法,且User的父类Model继承了dict类,所以当height字段不在User的attrs时依然不会报错,实际上输入任何的关键字参数都不会出错。ORM模型在u.save()时,是通过查找在__new__时__map__中的字段,也就是#6中的(id,name,email,password,age),通过sql语句动态的执行存储操作。
通过ORM模型看python对象创建过程的更多相关文章
- 【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理
原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attr ...
- Java中对象创建过程
本文介绍的对象创建过程仅限于普通Java对象,不包括数组和Class对象. 1.类加载检查 虚拟机遇到一条new指令时,首先去检查该指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用 ...
- Java中类加载过程和对象创建过程
类加载过程: 1, JVM会先去方法区中找有没有相应类的.class存在.如果有,就直接使用:如果没有,则把相关类的.class加载到方法区 2, 在.class加载到方法区时,会分为两部分加载:先加 ...
- java基础---类加载和对象创建过程
类中可以存在的成员: class A{ 静态成员变量: 非静态成员变量: 静态函数: 非静态函数: 构造函数 A(..){...} 静态代码块 static{...} 构造代码块 {...} } 类加 ...
- COM对象创建过程
在客户端需要调用COM组件时,通常调用windowAPI函数: STDAPI CoCreateInstance( REFCLSID rclsid, //创建的Com对象的类标识符(CLSID) LPU ...
- java类加载、对象创建过程
类加载过程: 1, JVM会先去方法区中找有没有相应类的.class存在.如果有,就直接使用:如果没有,则把相关类的.class加载到方法区 2, 在.class加载到方法区时,会分为两部分加载:先加 ...
- JBPM TaskInstance 对象创建过程
对象获得过程如下: 获得对象工厂--->工厂创建代理对象 TaskMgmtInstance tmi = executionContext.getTaskMgmtInstance(); TaskI ...
- Java内存区域与对象创建过程
一.java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则 ...
- OC对象创建过程
在利用OC开发应用程序中,须要大量创建对象,那么它的过程是什么呢? 比方:NSArray *array = [[NSArrayalloc] init]; 在说明之前,先把OC的Class描写叙述一下: ...
随机推荐
- "私人助手"NABCD分析
---恢复内容开始--- 团队开发项目“私人助手”需求分析NABCD模型: (1)N(Need需求):“私人助手”解决了几类人遇到非常多的事情,非常繁琐,“私人助手”为用户解决这个问题,让用户的工作更 ...
- 1001.A+B Format (20) 解题
代码入口(https://github.com/NSDie/object-oriented) 这题的解题思路我有两个: 第一个是两个数字相加然后判断位数,因为题目限制了范围1000000的绝对值以内嘛 ...
- alphe4
队名:massivehard 组员1:(组长:晓辉) 今天完成了哪些任务: 服务器基本架设完毕 明日计划: 服务器与客户端对接 用户手写记录功能的完善 还剩下哪些计划: 用户手写记录功能 服务器与客户 ...
- synchronized、锁、多线程同步的原理是咋样
先综述个结论: 一般说的synchronized用来做多线程同步功能,其实synchronized只是提供多线程互斥,而对象的wait()和notify()方法才提供线程的同步功能. 一般说synch ...
- JabRef学习笔记(一)
JabRef简介 JabRef is an open source bibliography reference manager. The native file format used by Jab ...
- python 创建目录
Python对文件的操作还算是方便的,只需要包含os模块进来,使用相关函数即可实现目录的创建. 主要涉及到三个函数 1.os.path.exists(path) 判断一个目录是否存在 2.os.mak ...
- vsftpd重启失败解决方法
vsftpd dead,but subsys locked vsftpd已死,但是subsys被锁 关于VSFTPD服务器重启失败,研究了一晚上,当virtual_use_local_privs=ye ...
- springcloud微服务实战:Eureka+Zuul+Feign/Ribbon+Hystrix Turbine+SpringConfig+sleuth+zipkin
相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展.会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新 ...
- python & dict & switch
python & dict & switch python 中是没用switch语句的,这应该是体现python大道至简的思想,python中一般多用字典来代替switch来实现. # ...
- IE userdata 原理 应用 详解
https://www.cnblogs.com/chyong168/archive/2012/04/24/2467505.html 在Internet Explorer 5中,Microsoft提供了 ...