Python的元编程案例
Python的元编程案例
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.什么是元编程
元编程概念来自LISP和smalltalk。 我们写程序是直接写代码,是否能够用代码来生成未来我们需要的代码吗?这就是元编程。
例如,我们写一个类class A,能否用代码生成一个类出来? 用来生成代码的程序称为元程序metaprogram,编写这种程序就称为元编程metaprogramming。
Python语言能够通过反射实现元编程。
Python中所有非object类都继承自object类 所有类的类型包括type类都是type type类继承自object类,object类的类型也是type类
二.type类
1>.查看type的构造方法
2>.使用type构造一个新类型(可以借助type构造任何类,用代码来生成代码,这就是元编程)
#!/usr/bin/env python
#_*_conding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie def __init__(self,name,age):
self.name = name
self.age = age def show(self):
print(self.__dict__) student = type("Student",(object,),{"school_address":"北京","__init__":__init__,"show":show}) print(student)
print(student.__dict__)
print(student.__base__)
print(student.mro()) student("jason",18).show()
<class '__main__.Student'>
{'school_address': '北京', '__init__': <function __init__ at 0x1006a2e18>, 'show': <function show at 0x10215fae8>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
<class 'object'>
[<class '__main__.Student'>, <class 'object'>]
{'name': 'jason', 'age': 18}
以上代码执行结果戳这里
三.使用type构建元类
1>.参考案例
#!/usr/bin/env python
#_*_conding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie #一个类可以继承自type类。注意不是继承自object类了。只要元类是ModelMeta,创建类对象时,就会调用ModelMeta的__new__方法
class ModelMeta(type):
def __new__(cls, name,bases,dict):
print(name)
print(bases)
print(dict,"======")
return super().__new__(cls,name,bases,dict) #继承自type,ModelMeta就是元类,它可以创建出其它类。
class A(metaclass=ModelMeta):
id = 1000
def __init__(self):
print("A.__init__") print("{0} 1 我是分割线 {0}".format("*" * 15)) #第二种 B继承自A后,依然是从ModelMeta的类型
class B(A):
def __init__(self):
print("B.__init__") print("{0} 2 我是分割线 {0}".format("*" * 15))
#第三种 元类就可以使用下面的方式创建新的类
p = ModelMeta("Person",(B,),{}) #D、E是type的实例
class D:pass #等效于 D = type("D",(),{})
E = type("E",(),{}) #F是元类
class F(ModelMeta):pass print("{0} 3 我是分割线 {0}".format("*" * 15)) print(type(A),A.__bases__)
print(type(B),B.__bases__)
print(type(p),p.__bases__) print("{0} 4 我是分割线 {0}".format("*" * 15))
print(type(D),D.__bases__)
print(type(E),E.__bases__)
print(type(F),F.__bases__)
A
()
{'__module__': '__main__', '__qualname__': 'A', 'id': 1000, '__init__': <function A.__init__ at 0x10195fae8>} ======
*************** 1 我是分割线 ***************
B
(<class '__main__.A'>,)
{'__module__': '__main__', '__qualname__': 'B', '__init__': <function B.__init__ at 0x10195fb70>} ======
*************** 2 我是分割线 ***************
Person
(<class '__main__.B'>,)
{} ======
*************** 3 我是分割线 ***************
<class '__main__.ModelMeta'> (<class 'object'>,)
<class '__main__.ModelMeta'> (<class '__main__.A'>,)
<class '__main__.ModelMeta'> (<class '__main__.B'>,)
*************** 4 我是分割线 ***************
<class 'type'> (<class 'object'>,)
<class 'type'> (<class 'object'>,)
<class 'type'> (<class '__main__.ModelMeta'>,)
以上代码执行结果戳这里
2>. 元类的应用
class Field:
def __init__(self, fieldname=None, pk=False, null=False):
self.fieldname = fieldname
self.pk = pk
self.null = null def __repr__(self):
return "<Field {} {} {}>".format(
self.fieldname,
self.pk,
self.null
) class ModelMeta(type):
def __new__(cls, name, bases, attrs:dict):
print('M ~~~~~~~~')
print(cls)
print(name, bases, attrs)
if not hasattr(attrs, 'db_table'):
attrs['db_table'] = name.lower()
primarykeys = []
for k, v in attrs.items():
if isinstance(v, Field):
if not v.fieldname or v.fieldname.strip() == '':
v.fieldname = k # 字段没有名字使用属性名 if v.pk:
primarykeys.append(v)
attrs['__primarykeys__'] = primarykeys
return super().__new__(cls, name, bases, attrs) class Model(metaclass=ModelMeta):
"""从Model继承的类的类型都是ModelMeta""" class Student(Model):
id = Field(pk=True, null=False)
name = Field('username', null=False)
age = Field() print("{0} 我是分割线 {0}".format("*" * 15))
print(Student.__dict__)
M ~~~~~~~~
<class '__main__.ModelMeta'>
Model () {'__module__': '__main__', '__qualname__': 'Model', '__doc__': '从Model继承的类的类型都是ModelMeta'}
M ~~~~~~~~
<class '__main__.ModelMeta'>
Student (<class '__main__.Model'>,) {'__module__': '__main__', '__qualname__': 'Student', 'id': <Field None True False>, 'name': <Field username False False>, 'age': <Field None False False>}
*************** 我是分割线 ***************
{'__module__': '__main__', 'id': <Field id True False>, 'name': <Field username False False>, 'age': <Field age False False>, 'db_table': 'student', '__primarykeys__': [<Field id True False>, <Field age False False>], '__doc__': None}
以上代码执行结果戳这里
四.元编程总结
元类是制造类的工厂,是用来构造类的类。 构造好元类,就可以在类定义时,使用关键字参数metaclass指定元类,可以使用最原始的 metatype(name, bases, dict)的方式构造一个类。
元类的 __new__() 方法中,可以获取元类信息、当前类、基类、类属性字典。
元编程一般用于框架开发中。
开发中除非你明确的知道自己在干什么,否则不要随便使用元编程 99%的情况下用不到元类,可能有些程序员一辈子都不会使用元类 Django、SQLAlchemy使用了元类,让我们使用起来很方便。
Python的元编程案例的更多相关文章
- Python类元编程
类元编程是指在运行时创建或定制类.在Python中,类是一等对象,因此任何时候都可以使用函数创建新类,而无需用class关键字.类装饰器也是函数,不过能够审查.修改,甚至把被装饰的类替换成其他类.元类 ...
- python之元编程
一.什么是元编程 元编程是一种编写计算机程序的技术,这些程序可以将自己看作数据,因此你可以在运行时对它进行内省.生成和/或修改. Python在语言层面对函数.类等基本类型提供了内省及实时创建和修改的 ...
- python之元编程(元类实例)
本实例是元类实例,功能是记录该的子类的类名,并以树状结构展示子类的类名. RegisterClasses继承自type,提供的功能是在__init__接口,为类创建了childrens的集合,并类名保 ...
- Python类元编程初探
在<流畅的Python>一书中提到: Classes are first-class object in Python, so a function can be used to crea ...
- Python元编程
简单定义"元编程是一种编写计算机程序的技术,这些程序可以将自己看做数据,因此你可以在运行时对它进行内审.生成和/或修改",本博参考<<Python高级编程>> ...
- ArcGIS Python编程案例-电子资料链接
ArcGIS Python编程案例(1)-Python语言基础 https://www.jianshu.com/p/dd90816d019b ArcGIS Python编程案例(2)-使用ArcPy编 ...
- python 面向对象编程案例01
# -*- coding: utf-8 -*- #python 27 #xiaodeng #面向对象编程案例01 class Behave(): def __init__(self,name): se ...
- python元编程(metaclass)
Python元编程就是使用metaclass技术进行编程,99%的情况下不会使用,了解即可. Python中的类和对象 对于学习Python和使用Python的同学,你是否好奇过Python中的对象究 ...
- Python 元编程 - 装饰器
Python 中提供了一个叫装饰器的特性,用于在不改变原始对象的情况下,增加新功能或行为. 这也属于 Python "元编程" 的一部分,在编译时一个对象去试图修改另一个对象的信息 ...
随机推荐
- weixin-js-sdk
场景:在h5移动端,实现分享朋友,分享朋友圈. 插曲:一开始我认为是不能做到分享的,主要是我从微信小程序的角度出发的,想着微信小程序都做不到分享朋友圈功能,那h5就更不能实现了,导致出现了错误的判断. ...
- C++内存管理5-处理new分配内存失败情况(转)
C++内存管理5-处理new分配内存失败情况(转) endl; 参考博客: https://www.cnblogs.com/findumars/p/9905195.html
- word中的总页数不包括封面、目录
删除分隔符:选项-显示-显示所有格式标记
- SQL Server:时间范围查询重叠
常常碰到要校验数据范围是否存在重叠冲突的情况,典型的场景是房间预订. 假如房间A已经有9月1日-9月10日的预订记录,当其它客人再来预订时,系统必须判断,不能与这个日期范围产生重叠. 有四种情况会产生 ...
- 工具分享:excel2json,将Excel表格转换为JSON
此次分享的是github上的一个开源小工具:excel2json,用于把Excel表转换成json对象,并保存到一个文本文件. 项目地址:https://github.com/neil3d/excel ...
- MYSQL:查询单表中不同邮箱最近一次发送状态
1.联系方式表-customer_contact: id email 1 123456@qq.com 2 987643@qq.com 3 hahaha@qq.com 2.发送邮件记录表-contact ...
- DS博客作业07--查找
1.本周学习总结(0--2分) 1.思维导图 2.谈谈你对查找运算的认识及学习体会. 2.PTA实验作业(6分) 本周要求挑3道题目写设计思路.调试过程.设计思路用伪代码描述.题目选做要求: 原则上题 ...
- [转帖]/proc/sys目录下各文件参数说明
/proc/sys目录下各文件参数说明 https://blog.csdn.net/luteresa/article/details/68061881 一.前言 本文档针对OOP8生产环境,具体优 ...
- 如何申请高德地图用户Key
打开网页https://lbs.amap.com/,进入高德开发平台. 单击箭头处[注册],打开注册页面.(如果您已注册为高德地图开发者可跳过此步骤,直接登录即可). 选择[成为个人开发者],如果您是 ...
- XXE任意文件读取(当xml解析内容有输出时)
利用XXE漏洞读取文件 参考:https://www.jianshu.com/p/4fc721398e97 首先找到登录源码如下: 由题目可以利用XXE漏洞读取文件 先登录用Burp Suite抓包: ...