廖雪峰的python教程有python元类编程示例,综合代码如下

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319106919344c4ef8b1e04c48778bb45796e0335839000#0

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') class ModelMetaclass(type):
def __new__(cls, name, bases, attrs):
if name=='Model':
return type.__new__(cls, name, bases, attrs)
#print('cls = %s' % cls)
#print('name = %s' % name)
#print('bases = %s' % bases)
#print('attrs = %s' % 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] = vfor k in mappings.keys():
#attrs基本就是可以通过类的__dict__属性得到
attrs.pop(k)
print(attrs)
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致
return type.__new__(cls, name, bases, attrs) class Model(dict, metaclass=ModelMetaclass):
def __init__(self, **kw):
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():
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)) class User(Model):
# 定义类的属性到列的映射:
id = IntegerField('id')
name = StringField('username')
email = StringField('email')
password = StringField('password') u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
u.save()

完整的代码如上,运行时函数的调用如下。

1、u = User(xxxxx)进行User类的实例化

2、实例化User类的时候,调用User的__init__,未显式实现,则调用父类的__init__

3、在父类Model发现了父类有metaclass=ModelMetaclass

4、去执行ModelMetaclass的__new__

5、在__new__中,ModelMetaclass可以访问到类的(注意,是类的,而不是类实例的)name、bases、attr,从而进行操作实现类的动态修改

此处,attr可以发现User类的类变量(不是类实例变量)id、name、email、password,在外部,这些类变量可以由User.__dict__接触到

6、执行__new__的代码中,有一个从attr中pop某些key的过程,因为如果不pop掉这些key,会导致运行时类变量覆盖掉类实例的变量,得到不期望的结果

7、执行__new__的过程中,User类动态生成了__mapping__和__table__属性

8、完成__new__的执行后,再进行Model.__init__,然后是User.__init__,完成实例化

为什么在这种情况下要进行元类编程呢?有什么好处呢?

python的元类编程的更多相关文章

  1. python 通过元类控制类的创建

    一.python中如何创建类? 1. 直接定义类 class A: a = 'a' 2. 通过type对象创建 在python中一切都是对象 在上面这张图中,A是我们平常在python中写的类,它可以 ...

  2. Python进阶开发之元类编程

    系列文章 √第一章 元类编程,已完成 ; 本文目录 类是如何产生的如何使用type创建类理解什么是元类使用元类的意义元类实战:ORM . 类是如何产生的 类是如何产生?这个问题肯定很傻.实则不然,很多 ...

  3. Python元类编程

    来源:http://python.jobbole.com/88582/ @property装饰器,是将类中的函数当做属性调用 Python类中定义的属性,如果属性名前面只有一个下划线,那么就是一种规范 ...

  4. PythonI/O进阶学习笔记_7.python动态属性,__new__和__init__和元类编程(上)

    content: 上: 1.property动态属性 2.__getattr__和__setattr__的区别和在属性查找中的作用 3.属性描述符 和属性查找过程 4.__new__和__init__ ...

  5. python3 元类编程的一个例子

    [引子] 虽然我们可以通过“class”语句来定义“类”,但是要想更加细粒度的控制“类”的创建,要使用元类编程才能实现. 比如说我们要实现这样的一个约束.所有项目中用到的类都应该要为它定义的方法提供文 ...

  6. Python 的元类设计起源自哪里?

    一个元老级的 Python 核心开发者曾建议我们( 点击阅读),应该广泛学习其它编程语言的优秀特性,从而提升 Python 在相关领域的能力.在关于元编程方面,他的建议是学习 Hy 和 Ruby.但是 ...

  7. 3.python元类编程

     1.1.propety动态属性 在面向对象编程中,我们一般把名词性的东西映射成属性,动词性的东西映射成方法.在python中他们对应的分别是属性self.xxx和类方法.但有时我们需要的属性需要根据 ...

  8. Python进阶:set和dict/对象引用、可变性和垃圾回收/元类编程/迭代器和生成器

    frozenset:不可变集合,无序,不重复 dict上的特性: 1. dict的key或者set的值 都必须是可以hash的(不可变对象 都是可hash的, str, fronzenset, tup ...

  9. 【转】Python 之 元类

    原文链接: https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python      http://python.jo ...

随机推荐

  1. Nginx笔记总结二十:nginx索引目录配置

    location / { autoindex on; autoindex_localtime on; }

  2. http,tcp,udp的报文格式

    http请求报文与响应报文:https://blog.csdn.net/qq_26565861/article/details/80969960 tcp与udp报文:https://www.cnblo ...

  3. 吴裕雄--天生自然 R语言开发学习:中级绘图(续一)

    #------------------------------------------------------------------------------------# # R in Action ...

  4. Memcached笔记——(三)Memcached使用总结

    为了将N个前端数据同步,通过Memcached完成数据打通,但带来了一些新问题: 使用iBatis整合了Memcached,iBatis针对每台server生成了唯一标识,导致同一份数据sql会产生不 ...

  5. linux下查找文件及查找包含指定内容的文件常用命令

    whereis <程序名称> 查找软件的安装路径-b 只查找二进制文件-m 只查找帮助文件-s 只查找源代码-u 排除指定类型文件-f 只显示文件名-B <目录> 在指定目录下 ...

  6. 理解 LinkedList

    java -version :jdk 1.8.0_191 构造 类内参数,方法 实现 基于双向链表实现. 插入时间复杂度 O(1) 查找时间复杂度 O(n) 删除时间复杂度 O(1) 修改时间复杂度 ...

  7. 【C#】WechatPay-API-v3 使用平台证书加密内容与应答|通知验签(SHA256 with RSA)

    官方暂时没有维护应答与通知签名的验证C#示例,找了些资料被困扰了一天终于调试通了,贴出来下 . 此类提供两个方法: 1.敏感信息加密,如身份证.银行卡号.(特约商户进件接口需要): 2.应答与通知签验 ...

  8. sql-- 找到重复数据并删除、有重复数据不插入或更新的处理方法

    表结构: 需求:找到相同的内容并删除 方法1: 通过分组找出筛选出count大于1的数据 group by可以利用聚合函数(count. sum. avg)进行分组 having 对分组的数据进行下一 ...

  9. 微信小程序状态管理工具 JStore

    微信小程序状态管理工具 JStore 闲着没事做,就想着给微信小程序写一个状态管理工具,名叫 JStore,这个状态管理工具是仿照 vuex 的几个方法来写的,所以有 vuex 的基础同学很容易理解. ...

  10. 用nodejs+express搭建前端测试服务端

    平时开发前端应用,如果没有现成的后端接口调试,又要保证前端进度,该怎么办呢,当然办法还是很多的,很多大牛都分享过很多经验,我也来说说我常用的方法. 请求本地数据文件 把本地数据放到程序指定目录,发起h ...