`
shuiyutian
  • 浏览: 11022 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

五分钟理解元类(Metaclasses)

 
阅读更多

五分钟理解元类(Metaclasses

真的,它并非巫术。


原文地址:http://blog.csdn.net/gzlaiyonghao/article/details/3048947

 

 “元类的魔幻变化比 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. 元类的定义与作用 元类是创建类的类,换言之,它们是...

    metaclasses:Dart 中元类的提案

    在标题"metaclasses:Dart 中元类的提案"中,我们可以理解为这是一个讨论或提议,旨在探讨如何在Dart中引入元类机制。通常,这样的提案会包含元类的基本概念、使用场景、语法结构以及可能带来的好处和挑战。 描述中...

    DEV-SAMPLES-JAVA-Putting_Metaclasses:来自“Putting Metaclasses to Work”一书的示例

    元类(Metaclasses)是面向对象编程中一个高级的概念,它扩展了传统的类概念,允许我们对类的行为进行编程。在Java中,虽然没有直接的元类概念,但是我们可以通过反射API和自定义注解处理器来实现类似的功能。本项目...

    Python中的Classes和Metaclasses详解

    它们在编写框架和库时特别有用,但不建议在日常编码中随意使用,因为不恰当的元类使用可能会导致代码难以理解和维护。 总的来说,Python的Classes提供了面向对象编程的基础,而Metaclasses则提供了更高级别的控制,...

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

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

    PyPI 官网下载 | owlmixin-2.4.0-py3-none-any.whl

    **元类(Metaclasses)**: 元类是创建类的类,它们可以用来修改类的行为。当你定义一个类时,Python默认使用`type`作为元类来创建这个类。元类的用途包括但不限于:验证类定义、添加默认方法、改变属性访问行为等。...

    Python库 | class_namespaces-0.5.6-py3-none-any.whl

    2. **元类(Metaclasses)**:元类是控制类行为的特殊类。`class_namespaces`可能利用元类来定制类的创建过程,如自动组织类属性、实现多重继承等。 3. **命名空间封装**:库可能提供了一种方式,使得类的成员可以...

    Python库 | class_namespaces-0.3.6-py3-none-any.whl

    4. **元类(Metaclasses)**:class_namespaces可能也涉及到了元类的使用,元类是Python中用于控制类行为的特殊类型,通过元类,我们可以在类被创建时执行自定义操作。 5. **类装饰器**:库可能包含了类装饰器的...

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

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

    Python库 | classutils-1.15.3-py2.py3-none-any.whl

    4. **元类(Metaclasses)**:元类是创建类的类,通过元类可以控制类的行为。`classutils`可能包含用于创建自定义元类的工具,帮助开发者更好地利用这个高级特性。 5. **枚举和混合类型**:库可能提供了对Python...

    PyPI 官网下载 | ExtensionClass-2.11.0b1.tar.gz

    4. **元类(Metaclasses)**:ExtensionClass也支持元类,元类是创建类的类,它允许对类的行为进行更深入的控制,比如在类创建时自动添加某些特性。 5. **增强的属性访问**:ExtensionClass提供了一种方式来拦截...

    Python计划. 面向对象语法精讲面. 面向对象进阶-时类运算操作实践.pdf

    Python的面向对象编程还涉及到其他高级概念,如抽象基类(Abstract Base Classes, ABCs)、元类(Metaclasses)和描述符(Descriptors),这些内容更深入,需要对Python的底层机制有较好的理解。 总的来说,掌握...

    python面试题超纲20道.rar_python面试

    1. **元类(Metaclasses)**:Python中的元类是用于创建类的类,理解元类可以帮助我们深入理解Python对象的创建过程。面试中可能会问到如何自定义元类以及如何使用元类实现特定的行为。 2. **装饰器(Decorators)*...

    ios runtime

    8. 类簇和元类(Class Clusters and Metaclasses) - 类簇模式让开发者可以隐藏真正的实现类,通过一个抽象类提供接口。 - 每个类都有一个对应的元类,元类存储了类的方法。 9. Objective-C语言特性使用 - 使用...

    meta模块安装教程.zip

    - **类型检查与元类(Metaclasses)**:元类是创建类的类,通过元类可以定制类的行为。比如,你可以创建一个元类,使得所有基于这个元类的类都自动添加某些属性或方法。 - **描述符(Descriptors)**:描述符是实现...

    面向对象

    在Python中,我们还可以使用类装饰器(class decorators)、元类(metaclasses)等高级特性来增强面向对象编程。类装饰器允许我们在不修改原有类代码的情况下,扩展或改变类的行为。元类是创建类的类,它们可以用来...

    cls_var_behavior:玩具项目与类变量一起玩

    7. **元类(Metaclasses)**:了解元类如何影响类变量,以及如何通过元类改变类变量的行为。 通过深入研究这个"cls_var_behavior"项目,开发者可以更全面地理解Python中的类变量,包括它们如何影响和被影响于类结构...

    python爱心代码高级代码.zip

    2. **元类(Metaclasses)**:元类是创建类的类,允许开发者自定义类的行为。在爱心代码中,元类可能会被用来自定义类的初始化,比如在创建对象时自动发送爱心信息。 3. **生成器(Generators)**:生成器是一种...

    Metaprogramming Ruby(Second Edition)

    8. **Metaclasses**:每个Ruby对象都有一个元类,用于存储对象的实例方法。通过元类,可以实现对象的自定义行为。 9. **宝石(Gems)和加载机制**:Ruby的包管理器Gem允许开发者轻松地共享和使用元编程库,如`...

    pro python

    #### 元类 (Metaclasses) 元类是用于创建类的类,它们控制类的创建过程。在Python中,可以通过定义自定义元类来控制类对象的创建,可以用来实现单例模式、自动注册类等高级功能。 #### 其他高级主题 除了上述知识...

Global site tag (gtag.js) - Google Analytics