Python元编程被称为“黑魔法”。Python界的传奇人物Tim Peters有云:

引用

Python的元编程这种黑魔法99%的人都无需了解,如果你拿不准是否应该用到它时,你不需要它.

OpenERP基本遵循了Tim Peters的教诲,但是却在6.1版本之后忍不住触及了一点点,从此游走于黑白两道之间:)
其实OpenERP中用到的元类(MetaClass)作用非常简单:就是在V6.1后我们在模块中所定义的实体类,不需要进行实例化,比如
OpenERPV6.1之前的实体类定义:

程序代码: [选择]

Class MyProduct(osv.osv):     _inherit="product.product"     pass
MyProduct()

在OpenERPV6.1之后则不需要上面的类的实例化过程了。即,不需要下面这句了:

程序代码: [选择]

MyProduct()

为了了解元类如何实现取消实例化过程,首先我们来看一下OpenERP中实体类的实例化过程到底做了些什么。
我们一般知道,Python类的调用或称为实例化,会生成该类的一个实例对象(instance object),比如:

程序代码: [选择]

class A(object):    ...:     def __init__(self, x):    ...:         self.x = x    ...:          In [2]: a = A(2)In [3]: a
Technorati 标签: Openerp, Python, 元编程
Out[3]: <__main__.A at 0x2ff2fd0>

a就是类A的一个实例对象。这是Python的基础知识,很好理解。但是,我要告诉你的是:在OpenERP中,MyProduct()并不产生MyProduct类的实例,甚至再深究的话,我们经常在代码中用到的pool.get('product.product')从对象池中获取的实例对象,也非这个MyProduct类所生成的实例。
这到底是怎么一回事?我们首先要了解什么是类的实例化,或者类的调用到底是怎样的一个过程,比如上例中A(2),其实其执行过程基本上可以分为两个部分,用Python 来表示就是:

程序代码: [选择]

n = A.__new__(A, 2)      #创建类的实例对象
if isinstance(n, A): A.__init__(n, 2)     #实例对象初始化

类A本身并没有定义__new__类方法,所以直接调用其父类即:object的__new__方法获得实例对象,如果获得的对象是A的实例则执行__init__方法
同样的,Myproduct所继承的osv.osv类(或OE6.1以后称为BaseModel)就有一个__new__方法,而这个方法返回的是None,所以按照上面的说明它都不会运行到实例初始化的部分,当然也就无法获得Myproduct的实例。
如果我们仔细分析代码,发现这个__new__的主要作用基本上就是下面这点代码:

程序代码: [选择]

        module_model_list = MetaModel.module_to_models.setdefault(cls._module, [])         if cls not in module_model_list:             if not cls._custom:                 module_model_list.append(cls)

其实MetaModel是一个元类(metaclass)等会儿要讲到,module_to_models则是这个类上的一个变量,其对应一个字典,字典的key对应每一个“模块”就是OpenERP的addons,其值对应这个模块中所定义的实体类(比如我们上例中的MyProduct)
所以调用实体类并没有实例化,只是就这样登记备案了一下,事实上只有在模块载入(loading)过程中才会对所注册的实体类实例化,其实也不是一般意义的实例化,而是要另外创造一个新类,再做实例化。(这部分以后有空再介绍)
那么问题回到原点,OpenERPV6.1以后如何做到,不调用实体类,即不运行BaseModel上的__new__方法就可以做到上述的类的注册过程。把OpenERP变色的那一点黑,这就出现了。对,就是那个叫MetaModel的家伙。在介绍MetaModel之前我们先快速的讲解一下Python的metaclass。
在Python中一切皆为“对象”, 类的实例是对象,类本身也是对象。类的实例对象是通过对类的调用获得的,那么类本身这个对象又是如何获得的呢?
其实上面的例子中类A的定义可以改写为:

程序代码: [选择]

A = type('A', (object,), {'__init__': lambda self,x: self.x=x})

从上面的代码可以看出类A是通过调用type,或者是通过对type的实例化来获得的,事实上默认情况下所有的类都是由type实例化获得,这个type类就是所生成类的元类。
类的实例对象可以对应五花八门我们定义的各种类,同理,我们是否可以定义除type以外用来生成类对象的五花八门的元类呢?答案当然是肯定的。看看我们的MetaModel:

程序代码: [选择]

class MetaModel(type):     ....

它与我们的普通的类定义没有什么差别,唯一需要注意的是其继承的父类是‘type',
而在OpenERP所有的实体类的基类BaseModel的类定义中有这么一句:

程序代码: [选择]

__metaclass__ = MetaModel

这句有特殊的含义,表示该类对象将由元类MetaModel实例化生成。在Python3.x中则用如下的语法:

程序代码: [选择]

Class MyProduct(metaclass=MetaModel, osv.osv)

还记得上面提到的类的实例化,__new__, __init__两步,元类的实例化也是一样。
我们看到MetaModel的__init__方法与上面提到的BaseModel类的__new__方法中有完全类似的代码:

程序代码: [选择]

        if not self._custom:             self.module_to_models.setdefault(self._module, []).append(self)

就是做了一个注册备案的动作。所以类对象本身产生的过程就已经注册了类,可以不用和6.0及以前版本的OpenERP每次定义实体类都要调用一下了。

« 最后编辑时间: 二月 25, 2013, 07:02:00 下午 作者 digitalsatori »

OpenERP高级实施顾问
上海先安科技 (http://cn.openerp.cn)
tony AT openerp.cn
021 50323731

转载于:https://my.oschina.net/tomora/blog/167256

OpenERP与Python 元编程相关推荐

  1. python函数myproduct_OpenERP与Python 元编程

    Python元编程被称为"黑魔法".Python界的传奇人物Tim Peters有云: 引用 Python的元编程这种黑魔法99%的人都无需了解,如果你拿不准是否应该用到它时,你不 ...

  2. 深入浅出Python元编程

    隔壁的Java 世界为了创建一个对象搞得鸡飞狗跳,这边的Python解释器倒是乐得清闲. (参见:<当创建对象时......>) 我作为他的第n任助手正式上岗. "老大,有程序员 ...

  3. python元编程之使用动态属性实现定制类--特殊方法__setattr__,__getattribute__篇

    问题:实现一个类,要求行为如同namedtuple:只存在给定名称的属性,不允许动态添加实例属性. 主要知识点在于: __setattr__,__getattr__,getattribute__,__ ...

  4. python元编程 实际应用_Python元编程

    简单定义"元编程是一种编写计算机程序的技术,这些程序可以将自己看做数据,因此你可以在运行时对它进行内审.生成和/或修改",本博参考<>将对元编程内容进行详细描述,若有不 ...

  5. 深入浅出使用python编程_深入浅出Python元编程

    来源:  码农翻身   作者:刘欣 隔壁的Java 世界为了创建一个对象搞得鸡飞狗跳,这边的Python解释器倒是乐得清闲. 我作为他的第n任助手正式上岗. "老大,有程序员要创建对象,怎么 ...

  6. 深入浅出Python元编程,不仅仅是Metaclass

    隔壁的Java 世界为了创建一个对象搞得鸡飞狗跳,这边的Python解释器倒是乐得清闲. (参见:<当创建对象时......>) 我作为他的第n任助手正式上岗. 更多Python视频.源码 ...

  7. python元编程详解

    什么是元编程 软件开发中很重要的一条原则就是"不要重复自己的工作(Don't repeat youself)",也就是说当我们需要复制粘贴代码时候,通常都需要寻找一个更加优雅的解决 ...

  8. python元编程运用_Python 中的元编程

    就像元数据是有关数据的数据一样,元编程就是编写用于操纵程序的某些程序.人们普遍认为,元程序就是生成其他程序的某些程序,但范式更加广泛.所有旨在自我读取.分析.转换或修改的程序都是元编程的范例.例如: ...

  9. Python元编程:控制你想控制的一切

    很多人不理解"元编程"是个什么东西,关于它也没有一个十分准确的定义.这篇文章要说的是Python里的元编程,实际上也不一定就真的符合"元编程"的定义.只不过我无 ...

最新文章

  1. 功能整合(二):轮播图(可控)、事件流
  2. php如何生成公钥私钥,php如何生成公钥私钥(代码)
  3. 微信小程序开发工具最新版本已更新下载(1.02.1804120)
  4. 派生类类型可以转换为基类类型,反之则不行
  5. simulink仿真及代码生成技术入门到精通_Simulink仿真零基础入门到精通实用教学教程 自学全套...
  6. java extern的作用_学习笔记之20-static和extern关键字2-对变量的作用
  7. 招聘 集群研发工程师
  8. 洛谷P3261 [JLOI2015]城池攻占(左偏树)
  9. poj3233Matrix Power Series
  10. 理解上下文切换带来的性能影响
  11. CodeForces - 379A
  12. 计算机与home键功能相反的是,home键是什么,虚拟home键如何使用
  13. Android 激活设备管理器后就无法再次打开设备管理器界面
  14. 干得好也要说得好| 这样向领导汇报,让你在职场上如鱼得水
  15. stl库的使用——队列queue和优先队列和优先队列小根堆(全家桶哎)
  16. esrally 如何进行简单的自定义性能测试?
  17. http实现大文件上传
  18. Oracle数据库实验4 Oracle数据库安全管理
  19. Struts2自定义类型转换器
  20. 稳定性高可用测试——各大厂质量保障实践分享汇总(下)

热门文章

  1. 好多Javascript日期选择器呀-4
  2. Asp.net 2.0 中将网站首页生成静态页的一个比较好的方法
  3. asp.net/c#字符格式化大总结
  4. 古怪的ConfigurationManager类
  5. 使用Windows7上的VS Code打开远程机Ubuntu上的文件操作步骤
  6. 【Qt】Ubuntu下Qt应用程序自启动设置
  7. php中连接两个值,php - 如何从两个表的连接中选择一个值? - SO中文参考 - www.soinside.com...
  8. mysql网页后台_jsp+servlet+mysql开发java web旅游网站,有后台管理系统
  9. matlab小波分析工具箱原理与应用_补充:频域特征值提取的MATLAB代码实现(小波分析)...
  10. 计算机网络 关于网速,关于电脑网速慢的说明