Python虽然是多范式的编程语言,但它的数据模型倒是 纯面向对象 的。与那些仅在语法层面声称纯OO的编程语言(如Java)相比,Python的这种纯粹性更加深刻骨髓。html
在Python的世界里,一切皆为对象:数值、序列、字典、函数、模块、文件、类、类实例 等等,无一例外(参考 Data model)。其中,“类也是对象” 的概念最让人匪夷所思,这彻底超越了传统的OO思想。python
元类(metaclass)是Python 2.2中引入的概念,利用元类能够 定制类的建立行为(Customizing class creation)。“元类” 的概念一样让人难以理解,然而理解 “元类” 是理解 “类也是对象” 的关键。编程
对于元类的理解,目前为止,最经典的阐述莫过于Stack Overflow上面的这篇帖子 What is a metaclass in Python?,e-satis 神通常的回复让人醍醐灌顶,看完后基本就了然于胸了。markdown
若是以为看英文比较吃力,这里有一篇中文译版 深入理解Python中的元类(metaclass)(注:英文原版最近有更新,但核心内容不变)。编程语言
对于类定义:函数
class Foo(Base): def say(self): print 'hello'
Python解释器 执行class语句 时,处理步骤以下:code
肯定元类mcls
。元类的查找优先级为:htm
__metaclass__
__metaclass__
__metaclass__
types.ClassType
;新式类:type
)使用元类mcls
建立类Foo
。建立语意等价于:对象
def say(self): print 'hello' # 元类的参数:mcls(name, bases, dict) Foo = mcls('Foo', (Base,), {'say': say})
建立成功后,类Foo
是 元类mcls
的 实例。blog
综上:建立类 实际上是一种更高级别的 实例化过程,本质上与 建立类实例 类似。
实例化过程 | 类 | 实例 | 语意形式 |
---|---|---|---|
建立类Foo | 元类mcls | 类Foo | class Foo: pass <=> Foo = mcls('Foo', (), {}) |
建立类实例foo | 类Foo | 类实例foo | foo = Foo() |
原则上,元类能够是:任何接受参数 name, bases, dict 并返回 类 的 可调用对象(参考 metaclass)。
例如元类能够是 函数:
def metacls_func(name, bases, dict): # do customizing here return type(name, bases, dict)
根据最佳实践指导,更好的习惯是使用 类 做为元类,典型风格以下:
class MetaCls(type): def __new__(cls, name, bases, dict): # do customizing here return super(MetaCls, cls).__new__(cls, name, bases, dict)
注意:
__new__
,还能够借助__init__
和__call__
来定制被建立的类1)经典类(Classic classes)
类Old
的三种等价定义:
class Old: pass class Old: __metaclass__ = types.ClassType Old = types.ClassType('Old', (), {})
类Old
是元类types.ClassType
的实例:
>>> isinstance(Old, types.ClassType) True
2)新式类(New-style classes)
类New
的三种等价定义:
class New(object): pass class New: __metaclass__ = type New = type('New', (), {})
类New
是元类type
的实例:
>>> isinstance(New, type) True
为全部类打上做者标签:
class AuthorTag(type): def __new__(cls, name, bases, dict): dict['__author__'] = 'RussellLuo' return super(AuthorTag, cls).__new__(cls, name, bases, dict) class MyBlog: __metaclass__ = AuthorTag class MyGitHub: __metaclass__ = AuthorTag
如今,类MyBlog
和类MyGitHub
都免费得到了做者签名:
>>> MyBlog.__author__ 'RussellLuo' >>> MyGitHub.__author__ 'RussellLuo'
请记住上面的简单案例,若是您想从本文中得到对Python元类仅有的一点印象。纸上得来终觉浅,绝知此事要躬行,开始吧。