python metaclass __new__ __init__ ___call__
来源:互联网 发布:哪个天气预报软件准确 编辑:程序博客网 时间:2024/05/16 09:30
转载 http://ju.outofmemory.cn/entry/105710
什么是 metaclass ?
In object-oriented programming, a metaclass is a class whose instances are
Wikipedia Metaclass
classes. Just as an ordinary class defines the behavior of certain objects, a
metaclass defines the behavior of certain classes and their instances.
简单的说, metaclass 就是 class 类型对象的 class, metaclass 的实例对象是 class 类型对象.
metaclass 能用来做什么 ?
我们就可以用 metaclass 来动态生成或者更改 class 的定义.
下面分别是通过传统 class 方式以及 metaclass 动态定义类 A
class A(object): a = 'I am a string.'
A = type('A', (object,), {'a': 'I am a string.'})
上面我们通过type
类的实例化来生成类A
, 如果我们想自定义类的生成, 我们可以以type
类为基 类派生出自定义的 metaclass.
注: 本文所有代码在 python2.6 下能执行通过, 不能确保在 python3 下无误.
继承type
类实现 metaclass
我们可以从type
类派生出新的 metaclass, 然后通过重新实现__new__
, __init__
, __call__
来实现类或者类实例的生成.
class Meta(type): def __call__(self): print 'Enter Meta.__call__: ', self obj = type.__call__(self) print 'Exit Meta.__call__: ', obj return obj def __new__(metacls, name, bases, dictionary): print 'Enter Meta.__new__:', metacls, name, bases, dictionary newClass = type.__new__(metacls, name, bases, dictionary) print 'Exit Meta.__new__: ', newClass return newClass def __init__(cls, name, bases, dictionary): print 'Enter Meta.__init__: ', cls, name, bases, dictionary super(Meta, cls).__init__(name, bases, dictionary) print 'Exit Meta.__init__'print 'Create class A'A = Meta('A', (object,), {})printprint 'Create instance of class A'A()
当我们运行上述的python文件, 会得到下面的输出结果:
$ python meta.pyCreate class AEnter Meta.__new__: <class '__main__.Meta'> A (<type 'object'>,) {}Exit Meta.__new__: <class '__main__.A'>Enter Meta.__init__: <class '__main__.A'> A (<type 'object'>,) {}Exit Meta.__init__Create instance of class AEnter Meta.__call__: <class '__main__.A'>Exit Meta.__call__: <__main__.A object at 0xb76a9ccc>$
通过上面的输出结果, 我们可以看出:
Meta.__new__
是用来生成类A
的类型对象, 我们可以在调用type.__new__
之前更改dictionary
变量来增加/修改/删除新生成类A
的成员变量/方法.Meta.__init__
是在生成类A
的类型对象后被调用类进行类A
的初始化. 第一个参数cls
是已经生成的类A
类型对象, 可以通过直接修改cls
来修改类的定义, 例如增加成员变量.Meta.__call__
是在生成类A
的实例对象时被调用的, 通过调用type.__call__
可以 生成该实例对象obj
, 之后我们可以直接修改obj
来实现实例对象的自定义.
如何使用 metaclass ?
- 我们可以直接调用
type
或者Meta
来动态生成新的类型对象A
:
A = Meta('A', (object,), {})
- 在定义类的时候, 重新指定该类的
__metaclass__
属性为Meta
:
class A(object): __metaclass__ = Meta # other member variables/methods definition
注意: 定义__metaclass__
生成的类A
会增加_A__metaclass
成员变量, 在某些场景下需要 了解到这个区别.
函数方式定义类的 metaclass
类的__metaclass__
可以是一个type
类型的子类, 也可以是一个函数, 该函数接受三个参数:
- name: 字符串类型, 表示新生成类型对象的名称
- bases: tuple类型, 新生成类型对象的父类列表
- properties: 字典类型, 新生成类型对象的属性
该函数必须返回新生成的类型对象. 下面例子是一个简单实现:
def meta_func(name, bases, properties): # you can modify bases, properties here to overide class creation return type(name, bases, properties)class A(object): __metaclass__ = meta_func
使用 metaclass 的案例
- 动态修改类的方法和属性, 例如给方法增加
decorator
- 类的序列化和反序列化
- 在生成类的时候进行接口检查和接口注册
- 对第三方库进行
monkey patch
- 生成代理类
- 动态mixin
- 控制实例对象的生成, 例如单体实例, 监控所有生成的实例对象
搜索stackoverflow 能找到大量使用 metaclass 的设计模式.
使用 metaclass 的原则
metaclass 会降低代码的可读性, 并且很多使用 metaclass 的场景都有替代方案, 因此必须牢记下面的 忠告:
Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don’t (the people who actually need them know with certainty that they need them, and don’t need an explanation about why).
Tim Peters Python Guru
- python metaclass __new__ __init__ ___call__
- python __new__ __init__
- Python __new__ ,__init__,__call__
- python __init__ __new__ __call__
- python __new__、__init__、__call__
- python __new__ 和 __init__
- python __new__和__init__
- python metaclass 和 __new__方法
- Python中__new__() 和 __init__()
- Python __new__与__init__说明
- python 中的 __new__ 和 __init__
- [深入Python]__new__和__init__
- [深入Python]__new__和__init__
- Python __init__与__new__区别
- python中__new__和__init__
- Python中的__init__和__new__
- python __new__ __init__ __call__详解
- python __init__和__new__之间的区别
- 彻底理解position与anchorPoint
- ZOJ 2112 Dynamic Rankings [树状数组套主席树]
- ubuntu批量改文件名
- 加人CSDN
- linux下C语言实现静态IP地址,网关的设置
- python metaclass __new__ __init__ ___call__
- PHP笔试题
- tomcat部署项目如何去掉项目名称
- android通讯录实例(二)
- iOS开发UI篇—CAlayer层的属性
- Android从搭建环境到写第一个程序
- 史上最小巧的blink+cc(硬件合成层)出炉
- Caffe的卷积原理
- android 控件的setClickable、setEnabled 、setFocusable