`
javayestome
  • 浏览: 1041264 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

[Python]五分钟理解元类(Metaclasses)

阅读更多

五分钟理解元类(Metaclasses

真的,它并非巫术。


原文地址:http://www.voidspace.org.uk/python/articles/five-minutes.shtml

日期:16 September, 2008.

译者:赖勇浩(http://blog.csdn.net/lanphaday

“元类的魔幻变化比 99% 的用户所担心的更多,当你搞不懂是否真的需要用它的时候,就是不需要。”

—Tim Peters

本文源于在 PyCon UK 2008 上的一个快速演讲。

元类被称为 Python 中的“深奥的巫术”。尽管你需要用到它的地方极少(除非你基于 zope 编程),可事实上它的基础理论其实令人惊讶地易懂。

一切皆对象

  • 一切皆对象

  • 一切都有类型

  • class”和“type”之间本质上并无不同

  • 类也是对象

  • 它们的类型是 type

以前,术语 type 用于内置类型,而术语 class 用于用户定义的类,但自 Pythoon 2.2 以来“class”和“type”本质上并无不同。

对于旧风格(old-style)类的类型是 types.ClassType

真的,这是真的

Python 2.5.1 (r251:54869, Apr 18 2007, 22:08:04)
>>> class Something(object):
... pass
...
>>> Something
<class '__main__.Something'>
>>> type(Something)
<type 'type'>

从这里可以看出在交互式解释器中创建的类是一个 first class 的对象。

类的类是……

它的元类……

就像对象是类的实例一样,类是它的元类的实例。

调用元类可以创建类。

确切来说,Python 中的其它对象也是如此。

因此当你创建一个类时……

解释器会调用元类来生成它……

定义一个继承自 object 的普通类意味着调用 type 来创建它:

>>> help(type)

Help on class type in module __builtin__:

class type(object)

| type(object) -> the object's type

| type(name, bases, dict) -> a new type

type 的第二种用法尤为重要。当 Python 解释器在执行一条类定义语句时(如例子中最初的两行代码之后),它会用下面的参数调用 type

  • 字符串形式的类名

  • 元组形式的基类序列——在我们的例子中是只有一个元素的元组(’one-pl’[1],如(object,)

  • 包括由名字影射的类成员(类属性、方法等)的字典

简单模拟

>>> def __init__(self):
... self.message = 'Hello World'
...
>>> def say_hello(self):
... print self.message
...
>>> attrs = {'__init__': __init__, 'say_hello': say_hello}
>>> bases = (object,)
>>> Hello = type('Hello', bases, attrs)
>>> Hello
<class '__main__.Hello'>
>>> h = Hello()
>>> h.say_hello()
Hello World

以上代码创建了类属性的字典,然后调用 type 来创建了名为 Hello 的类。

__metaclass__ 的魔法

只要在类定义中把 __metaclass__ 设置为任意有着与 type 相同参数的可调用对象,就能够提供自定义的元类。

通常使用从 type 继承的方法:

class PointlessMetaclass(type):
def __new__(meta, name, bases, attrs):
# do stuff...
return type.__new__(meta, name, bases, attrs)

重要的是在 __new__ 方法中我们能够读取或改变传入的用以创建新类的参数。从而能够内省属性字典和改动、增加或者删除成员。

尽管当实例化一个类时这两个函数都会被调用,但覆盖 __new__ __init__ 更为重要。__init__ 初始化一个实例,而 __new__ 的职责是创建它。因此如果元类用以自定义类的创建,就需要覆盖 type __new__

使用新类而非仅仅提供工厂函数的原因在于如果使用工厂函数(那样只是调用 type)的话元类不会被继承。

In Action...

>>> class WhizzBang(object):
... __metaclass__ = PointlessMetaclass
...
>>> WhizzBang
<class '__main__.WhizzBang'>
>>> type(WhizzBang)
<class '__main__.PointlessMetaClass'>

WhizzBang 是一个类,但它现在已经不是 type 的实例,而是我们自定义的元类的实例了……

这有什么用?

很好的问题,元类将用在创建使用了它的新类时调用,这里是一些关于这样做的好处的观点:

  • 装饰(Decorate)类的所有方法,用以日志记录或者性能剖分。

  • 自动 Mix-in 新方法

  • 在创建时注册类。(例如自动注册插件或从类成员创建数据库模式。)

  • 提供接口注册,功能自动发现和接口适配。

  • 类校验:防止子类化,校验所有的方法是否都有 docstrings

最重要之处在于元类中是在最后对 type 的调用时才真正创建类,所以可以自由地随你喜欢地改变属性字典(以及名称和元组形式的基类序列)。

一些流行的 Python ORMObject Relational Mappers(对象关系影射),用以和数据库协同工作)也如此使用元类。

哦,还有因为元类是继承的,所以你能够提供一个使用了你的元类的基类,而继承自它的子类就无需显式声明它了。

但是……

我曾未需要使用它来编写代码……(我们用它来剖分,也在 Ironclad 项目广泛应用它,但我不编写这些)。

还有,这一切只适用于 Python 2.x,其中的机制在 Python 3 中已经改变了。

type(type) is type

Python 2.6 中现在也可用使用 class decorators 来实现许多以前可能需要用元类来实现的东西。

最后,还有一个极尽奇技淫巧的例子(稍为深入,但仍然不难消化),可以去看看 The Selfless Metaclass。它通过字节码和方法签名重写来避免显式地声明 self

[1]

'one-pl'是指只有一个元素的元组。

分享到:
评论

相关推荐

    五分钟理解元类(Metaclasses)

    元类(Metaclasses)是Python中一种深层次的高级特性,它允许程序员对类的创建过程进行修改。根据提供的文件内容,我们可以总结出以下关于元类的知识点: 1. 元类的定义与作用 元类是创建类的类,换言之,它们是...

    Python中的Classes和Metaclasses详解

    Python中的Classes和Metaclasses是理解面向对象编程的关键概念,特别是在Python这种动态类型的语言中。首先,让我们深入探讨一下类(Classes)。 类是Python中用于创建对象的蓝图。类定义了对象的属性(attributes...

    Python库 | metaclass-1.0-py2.py3-none-any.whl

    这个库特别之处在于它与Python中的元类(metaclasses)有关,元类是Python面向对象编程中的一个高级概念。 元类是Python中创建类的类。通常,当我们定义一个类时,Python会默认使用`type`作为元类来创建这个类。元...

    Fluent Python(最新版 原版 高清 带书签)

    此外,还介绍了Python的特性(Descriptors)和元类(Metaclasses),这些都是理解Python对象模型的关键。 4. **函数式编程**:Python支持函数式编程风格,如高阶函数、map、filter、reduce等。书中将阐述如何利用...

    python编程指南pdf

    首先,Python 3.1引入了对元类(metaclasses)的改进,使得元类更加灵活和易于使用,这在设计复杂类结构或实现特定行为时非常有用。其次,字典(dict)在3.1版本中进行了优化,提供了更高效的操作,如字典合并和有序...

    fluent python.zip

    1. **元编程**:Python的元类(metaclasses)和描述符(descriptors)是其强大的元编程能力的体现。元类可以控制类的行为,而描述符则能改变属性访问的默认行为。 2. **列表推导式与生成器表达式**:这些高级语法...

    Python-pythonlearnersglossary对Pardonjargon的解释帮助Python新手理解Pythonista黑话

    10. **元类(metaclasses)**:元类是创建类的类,可以用来定制类的行为。 11. **GIL(Global Interpreter Lock)**:Python解释器的一个特性,确保同一时刻只有一个线程执行Python字节码,这限制了Python在多核环境下...

    Python 中文手册 v2.4(HTML)

    3. **元类(Metaclasses)**:元类是创建类的类,Python 2.4引入了更直接的元类使用方式,使得元编程变得更加灵活。 4. **异常处理的`with`语句**:虽然在Python 2.4中引入,但直到Python 2.5才完全实现。`with`...

    Python高级编程(带完整书签目录)

    首先,书中可能涉及的Python高级主题包括元类(metaclasses)、装饰器(decorators)、生成器(generators)、上下文管理器(context managers)以及高级数据结构的实现。这些内容是Python进阶学习的关键,它们能...

    Python进阶(Intermediate Python) 中文PDF彩色版

    6. **元编程(Metaprogramming)**:元编程是指在运行时修改或生成代码的能力,Python提供了丰富的元编程工具,如元类(metaclasses)、反射等。 7. **高级数据结构**:除了基础的列表、字典和集合,Python还提供了...

    Python进阶_pythonpdf_python_

    Python支持元类(metaclasses),允许我们定制类的行为。通过元类,可以实现如动态属性添加、类型检查和自动生成API文档等功能。 ### 装饰器 装饰器是Python中的一个强大工具,用于修改或增强函数、方法或类的行为...

    FluentPython英文正式版(非提前版)

    6. 元编程:理解属性(properties)、属性描述符(attribute descriptors)、类装饰器(class decorators)以及元类(metaclasses)的工作原理。元编程是高级Python编程中非常强大的特性,可以帮助程序员编写出能够...

    Python中文手册v2.4

    这个版本引入了许多新特性,包括对元类(metaclasses)的支持,增强了异常处理,以及改进了垃圾回收机制。以下是一些关键的知识点: 1. **元类**:元类是创建类的类,它允许开发者对类的行为进行定制。在Python 2.4...

    VS2010的Python插件及快速入门教程和具体源码

    这个版本引入了一些新特性,如增强的元类(metaclasses)、新的v3.3虚拟机以及异步I/O支持。安装Python 3.3.1意味着你可以使用VS2010的Python插件来开发基于这个版本的Python程序。 **Python快速入门教程** ...

    Python官方2.2版本exe安装包

    5. **元类(Metaclasses)**:Python 2.2开始支持元类,元类可以控制类的创建,为高级编程和元编程提供了强大的工具。元类通过`__metaclass__`属性或`metaclass`关键字在类定义中指定。 6. **Unicode支持增强**:...

    Python官方2.0.1版本exe安装包

    5. **元类(metaclasses)**:Python 2.0引入了元类的概念,允许程序员自定义类的行为。这是一个高级特性,可以用于实现诸如类型检查、属性动态生成等高级功能。 6. **__slots__特性**:在类定义中使用`__slots__`...

    Python进阶(Intermediate_Python)_中文PDF彩色版pdf.7z

    Python的元类(metaclasses)、类装饰器和属性装饰器都是元编程的例子,它们可以用于实现自定义的行为和动态类型系统。 7. **性能优化**:Python虽然是一门解释型语言,但仍然可以通过各种手段进行性能优化,例如...

    python高级编程html文档

    2. **元编程**:Python提供了元类(metaclasses)和装饰器(decorators),允许程序员在运行时修改类的行为,或者在不改变原有代码的基础上增强函数的功能。 3. **面向对象编程**:深入理解类和对象,包括继承、...

    python官方2.4.3版本msi安装包

    - **元类(metaclasses)**:允许自定义类的行为,增强了面向对象编程的灵活性。 - **import优化**:提高了模块导入速度,通过引入`__import__`函数的缓存机制。 4. **兼容性**: Python 2.4.3可以运行在多种...

Global site tag (gtag.js) - Google Analytics