python的MetaClass的代码分析。基于廖雪峰博客代码
# 一张表一个类,表内每一行就是一个实例
'''
一个单独的元类使用的程序分析。
''' 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) # self.__class__:得到当前实例的类 self.__class__.__name__:得到当前实例的类的名字
# self.name:实例名字 __repr__ = __str__ 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这个元类的__new__()方法在本程序中的作用:
# 1.在依据ModelMetaclass创建Model时,由Model向元类传入的参数为:cls:<class '__main__.ModelMetaclass>;name:Model;bases()传入的bases是一个tuple:(<class 'dict'>,),attrs是一个由Model类中的所有的方法名和方法函数地址组成的dict.
# 然后再传入该元类后,执行__new__(),由于name=='Model'所以返回由type('Model', (dict,), attrs)所组成的类。return了,不往下执行。
# 2.在准备创建User类时,可以见class User上的注释。此时name==User。在__new__()内执行时。if失效。往后运行,创建一个名为mappings的dict。mappings的作用是用来存储此时User里面的4个属性(id,name,password,email).并将作为一个属性返回。
# 由于attrs包含了User中的所有的属性。所以先要用isinstance(v,Field)判断是不是id/name/password/email中的一个。若找到,则复制如mappings中。
# 删除User的4个id/name/password/email属性(防止造成实例的属性遮盖类的同名属性)。
# 添加两个属性__mappings__和__table__。并把最后的attrs作为最后要生成的名为User的类的所有方法。 class ModelMetaclass(type):
def __new__(cls, name, bases, attrs):
# print('hello',cls,'---',name,'---',bases,'---',attrs)
if name == 'Model': # 如果名字==Model。那么久用type创建一个类。在这里,name:要创建的类的名字;bases:要创建的类的父类;attrs:类的方法与函数对照字典。
# print(attrs)
return type.__new__(cls, name, bases, attrs)
# return super().__new__(cls, name, bases, attrs)
print('Found model:%s' % name)
mappings = dict()
for k, v in attrs.items():
if isinstance(v, Field):
print('Found mapping: %s==>%s' % (k, v))
mappings[k] = v
for k in mappings.keys():
# print([(k, v) for k, v in attrs.items() if isinstance(v, Field)])
attrs.pop(k)
attrs['__mappings__'] = mappings
attrs['__table__'] = name
# print(attrs)
return type.__new__(cls, name, bases, attrs) class Model(dict, metaclass=ModelMetaclass):
def __init__(self, **kw):
# print(Model.mro())
# 调用父类dict类的__init__方法,需要传入一个dict。
super(Model, self).__init__(**kw) def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value):
self[key] = value def save(self):
fields = []
params = []
args = []
for k, v in self.__mappings__.items():
# print(v.name)
fields.append(v.name)
params.append('?')
# 当u=User(......)后,u就具有了4个属性u.id=12345 u.name='Michael' u.email='test@orm.org' u.password='my-pwd'
args.append(getattr(self, k, None))
sql = 'insert into %s (%s) values (%s)' % (self.__table__,
','.join(fields),
','.join(params))
# join()函数
# 语法: 'sep'.join(seq) 该例为:','.join(fields) 对应的:sep=, seq=fields.
# 参数说明
# sep:分隔符。可以为空
# seq:要连接的元素序列、字符串、元组、字典
# 上面的语法即:以sep作为分隔符,将seq所有的元素合并成一个新的字符串
# 返回值:返回一个以分隔符sep连接各个元素后生成的字符串
print('SQL: %s' % sql)
# print(args)
print('ARGS: %s' % str(args)) # 当用户定义一个class User(Model)时,Python解释器首先在当前类User的定义中查找metaclass,如果没有找到,
# 就继续在父类Model中查找metaclass,找到了,就使用Model中定义的metaclass的ModelMetaclass来创建User类,
# 也就是说,metaclass可以隐式地继承到子类,但子类自己却感觉不到。 # 在创建User时,程序会先执行完里面的4条属性声明语句。然后再将包含该4条属性和所有的方法组成一个dict。传入ModelMetaclass的__new__中。 # 通过使用元类,程序员可以在这里自定义一个类(数据库的一张表)需要输入哪些元素。 class User(Model):
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password') # 在这里时,User类里面没有4个单独的id/name/password/email属性,只有__mappings__和__table__属性。 # print(type(User.id))
# print(dir(User))
u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
# print(u.name.name)
# print(u.id.name)
# print(u.email.name)
# print(u.password.name)
# print(dir(u.id))
# print(u.id.name)
u.save()
# print(dir(Model))
python的MetaClass的代码分析。基于廖雪峰博客代码的更多相关文章
- step2: 爬取廖雪峰博客
#https://zhuanlan.zhihu.com/p/26342933 #https://zhuanlan.zhihu.com/p/26833760 scrapy startproject li ...
- git入门笔记汇总——(廖雪峰博客git入门)
本文内容是对廖雪峰老师Git教程做的笔记,外加一些自己的学习心得,还抱着学以致用的心态来实践一番 如有显示错误 请移步本人github:git教程小结 Git学习笔记 Git简介 安装Git 创建版本 ...
- python 3 廖雪峰博客笔记(二) python解释器
python 解释器用于理解 python代码,存在多种python解释器 CPython 官方版本python解释器,用C语言开发,使用最广泛 IPython 基于CPython,在交互方式上有所增 ...
- python 1 学习廖雪峰博客
输出 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字.比如输出'hello, world',用代码实现如下: >>> print('hello, world') p ...
- python 3 廖雪峰博客笔记(三) 命令行模式与交互模式
python 的代码一般保存为 .py结尾的文本文件格式 比如 add.py 里写下如下内容 100 + 200 执行 add.py有两种方式: 1. 命令行方式:将python代码写入脚本中执行 p ...
- python 3 廖雪峰博客笔记(一) python特性
python 是一种解释性语言,代码在执行时会一行一行翻译成CPU能理解的机器语言. python 的特点是简单优雅. python 的优点是 代码优雅 基础代码库丰富,包括网络.文件.GUI.数据库 ...
- git 廖雪峰博客笔记
其他参考 http://www.softwhy.com/article-8498-1.html 本地模拟多用户来学习 参考 其实就是克隆两个目录,两个目录的git config 不同的名字和邮箱, ...
- Linux内核分析第二周学习博客——完成一个简单的时间片轮转多道程序内核代码
Linux内核分析第二周学习博客 本周,通过实现一个简单的操作系统内核,我大致了解了操作系统运行的过程. 实验主要步骤如下: 代码分析: void my_process(void) { int i = ...
- 基于Hexo搭建博客并部署到Github Pages
基于Hexo搭建博客并部署到Github Pages 之前在简书上写东西,觉得自己还是太浮躁.本来打算用Flask自己写一个,以为是微框架就比较简单,naive.HTML.CSS.JS等都要学啊,我几 ...
随机推荐
- MySQL -Naivacat工具与pymysql模块
Navicat 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库. 官网下载:https ...
- Asp.Net MVC Identity 2.2.1 使用技巧(一)
开发环境:vs2015 UP3 or vs2017RC 项目环境:asp.net 4.6.1 identity版本为:asp.net identity 2.2.1 1.创建项目. 没什么好说 ...
- August 14th 2017 Week 33rd Monday
Life is like a watch, you can return to the starting point, they are not yesterday! 人生就像钟表,可以回到起点,却已 ...
- [BZOJ 2186][SDOI 2008] 莎拉公主的困惑
2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 4519 Solved: 1560[Submit][S ...
- pyenv - python版本管理
1. 安装pyenv brew install pyenv 2. 安装python其它版本(如:python 3.6.7) pyenv install --list #查看可以安装的python版本 ...
- 020.2.1 system
内容:System的常用方法1.currentTimeMillis()方法(与1970年相差多少毫秒),2.Properties getProperties():获取系统属性3.Set<Str ...
- 【LGP5162】WD与积木
题目 场面过度玄学,容易引起不适 我们发现我们要求的这个期望由分母和分子两部分构成 易发现 \[Ans=\frac{\sum_{i=1}^nS_2(n,i)\times i\times i!}{\su ...
- [HEOI2012]朋友圈
题目 我们发现我们要求的是一个最大团问题,众所周知这是一个\(NP\)难问题,除了爆搜没有什么别的方法,但是这道题我们可以根据图的特殊性质入手 我们如果把\(B\)国的人分成奇数和偶数两类,就会发现奇 ...
- [Python 多线程] GIL全局解释器锁 (十三)
Queue 标准库queue模块,提供FIFO(先进先出)的Queue.LIFO(后进先出)的队列.优先队列. Queue类是线程安全的,适用于多线程间安全的交换数据.内部使用了Lock和Condit ...
- LayIM.AspNetCore Middleware 开发日记(七)Asp.Net.Core.SignalR闪亮登场
前言 前几篇介绍了整个中间件的构成,路由,基本配置等等.基本上没有涉及到通讯部分.不过已经实现了融云的通讯功能,由于是第三方的就不在单独去写.正好.NET Core SignalR已经出来好久了, ...