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使用了元类,让我们使用起来很方便。

最新文章

  1. java web学习总结(四) -------------------HTTP协议
  2. ViewPager的监听事件失效
  3. MmSystem播放Wav格式声音
  4. Android 联系人信息的读取注意判断是否为NULL Android联系人的删除实质
  5. 【Itext】解决Itext5大并发大数据量下输出PDF发生内存溢出outofmemery异常
  6. 使用less函数实现不同背景的CSS样式
  7. javascript权威指南(1)
  8. js中的“闭包”
  9. 获取手机 IP
  10. es6的一些知识点
  11. 数据库——MongoDB——&gt;Java篇
  12. 使用C#+XPath+HtmlAgilityPack轻松搞一个资源下载器
  13. Go语言中Loop的注意点
  14. connect设置连接超时
  15. go 的数据类型
  16. Web三层-UI/BLL/DAL/MODEL
  17. Vue2.0 新手完全填坑攻略—从环境搭建到发布
  18. python基础介绍二
  19. [原]unity5 AssetBundle 加载
  20. Android 获得本地IP地址、外网IP地址、本设备网络状态信息、本地Mac地址

热门文章

  1. sqlserver2012 用户指定数据库访问权限
  2. Redis 分布式锁的正确实现方式(Java版)[转]
  3. [ ceph ] BlueStore 存储引擎介绍
  4. Centos7——无法访问Windows系统的分区
  5. Navicat 创建oracle表空间、新建用户、授权
  6. vue 项目不显示样式 排版错乱
  7. SQL SERVER 数据库查询表信息
  8. [BZOJ3230]相似子串(后缀数组)
  9. C# vb .net实现翻转特效滤镜
  10. 易百教程人工智能python修正-人工智能无监督学习(聚类)