python 的 metaclass
Posted 等待未知
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 的 metaclass相关的知识,希望对你有一定的参考价值。
Python 是一种非常灵活的语言,这使得它具有很强的表达力,metaclass 也是这种强大表达力的一个体现。
啥是 metaclass 呢? meta- 这个词似乎这些年越来越流行,翻译成中文,一般是 元..., 比如元认知,元数据。“元什么” 一般表示的含义是 什么的什么, 元数据即数据的数据,元认知即认知的认知。metaclass 就是类的类。粗略的说,执行一个 metaclass 会得到一个新的 class, Python 内置的 type 就可以看成一个metaclass。
metaclass 有什么用呢?这个问题的答案和另一个问题的答案其实有些类似: decorator 有什么用呢? metaclass 和 decorator 都属于元编程。元编程,可以理解为让程序来写程序。当然,这里说的不是人工智能来写程序啊,只是一种固定模式的程序转换。让程序来写程序的目的,我感觉常见的一般是三个:一是减少重复性的 boilerplate, 这方面最典型的例子是 C 语言里的宏;第二是提供简洁易用的用户接口,比如python web 框架 Falsk 里面的装饰器 @app.route, 你不用它,也可以注册 url endpoint, 但是不如这个简洁;第三,一段代码的逻辑是动态的,但是一旦初始化完成之后代码逻辑就可以确定了,也很适合使用元编程,比如,一个函数内部两种逻辑,选择哪种依赖程序的某个配置,这个配置在编码阶段无法确定,但是一旦程序启动读取了配置之后,这个配置也是不会变的,这时就可以使用装饰器来动态定义该函数。
Python 中的 decorator 是可以装饰 class的, 那为什么还需要 metaclass 呢。PEP 3115 里做了解释, decorator 属于一种后处理,对一个类定义能施加的影响其实很有限,而metaclass 会深度介入一个类的创建过程。
metaclass 如何影响一个类的创建
python 官方的 Language Reference 中的 Data model一章有详细的说明,此处简单转述一下原理(忽略了一些细节)。
- 确定一个类的 metaclass, 如果一个类在定义时显示指定了 metaclass, 则使用该 metaclass, 否则使用 type() 作为其metaclass
- 准备namespace, 这个 namespace 是类内部的 namespace, 是一个类似字典的对象,用于保存类的各种属性。这个 namespace 是通过 metaclass.__prepare__(name, bases, **kwds) 得到。
- 在上述 namespace 中执行被定义的类的 body。
- 调用 metaclass(name, bases, namespace, **kwds) 创建被定义的类。
metaclass 示例
可参考 PEP3115 中的示例: https://www.python.org/dev/peps/pep-3115/#example
以上是关于python 的 metaclass的主要内容,如果未能解决你的问题,请参考以下文章