`
shuiyutian
  • 浏览: 10644 次
  • 性别: 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)

    NULL 博文链接:https://swingfly.iteye.com/blog/540835

    Metaclasses Proposal for C++

    Metaclasses let programmers write a new kind of efficient abstraction: a user-defined named subset of classes that share common characteristics – including user-defined rules, defaults, and generated...

    metaclasses:Dart 中元类的提案

    元类 Dart 中元类的提案

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

    DEV-SAMPLES-JAVA-Putting_Metaclasses “将元类用于工作:面向对象编程的新维度”一书中的示例 执照 编译工具 作者 艾拉·R·福尔曼 斯科特·H·丹佛斯 链接

    Python中的Classes和Metaclasses详解

    主要介绍了Python中的Classes和Metaclasses详解,属于基础知识中类与对象的概念部分的深入,需要的朋友可以参考下

    MMXX - Modules & Metaclasses ++-开源

    C++ 脆弱基类问题(完全可修改的共享库/框架/插件架构)以及接口存储库/对象适配器(类属性查询,从外部代码和网关以编程方式调用方法)的解毒剂。

    Learning Python 5th edition

    Get a comprehensive, in-depth introduction to the core Python language with this hands-on book....Learn advanced Python tools, including decorators, descriptors, metaclasses, and Unicode processing

    Learning Python, 5th Edition

    If you want to write efficient, high-quality code that's easily integrated with other languages and tools, this hands-on book ... including decorators, descriptors, metaclasses, and Unicode processing

    Python 中 Meta Classes详解

    首先,在认识metaclass之前,你需要认识下python中的class。python中class的奇怪特性借鉴了smalltalk语言。大多数语言中,classes仅仅是用于描述怎样创建一个对象的代码端。在某种程度上说,python中的class也是这样...

    Learning Python 5th Edition(Python学习手册,第5版,英文)

    Learning Python, Fifth Edition by Mark Lutz Get a comprehensive, in-depth introduction to the core...- Learn advanced Python tools, including decorators, descriptors, metaclasses, and Unicode processing

    Professional.Python.1119070856

    Chapter 5: Metaclasses Chapter 6: Class Factories Chapter 7: Abstract Base Classes Part III: Data Chapter 8: Strings and Unicode Chapter 9: Regular Expressions Part IV: Everything Else Chapter 10: ...

    Python Cookbook, 2nd Edition (epub 格式)

    and on new, advanced tools introduced in Python 2.2 and following releases (custom descriptors, decorators, metaclasses). Each chapter contains an introduction, written by an expert in the field, ...

    Mastering Python(PACKT,2016)

    It covers how to create different decorators, generators, and metaclasses. It also introduces you to functools.wraps and coroutines and how they work. Later on you will learn to use asyncio module ...

    Professional Python(Wrox,2015)

    Coverage includes Decorators, Context Managers, Magic Methods, Class Factories, Metaclasses, Regular Expressions, and more, including advanced methods for unit testing using asyncio and CLI tools....

    Professional Python, Luke Sneeringer, 2016

    CHAPTER 5 Metaclasses CHAPTER 6 Class Factories CHAPTER 7 Abstract Base Classes PART III DATA CHAPTER 8 Strings and Unicode CHAPTER 9 Regular Expressions PART IV EVERYTHING ELSE CHAPTER 10 Python 2 ...

    演示文稿:高级Python主题的演示文稿集合

    主题包括: Python之道: object和type之间的复杂关系以及元类,类和实例之间的关联方式( )。 Python中的MRO :使用C3线性化( )在多个继承中的方法解析顺序。 Python中的元类和元编程( )。 Python中的函数式...

    Mastering Python [2016]

    It covers how to create different decorators, generators, and metaclasses. It also introduces you to functools.wraps and coroutines and how they work. Later on you will learn to use asyncio module ...

Global site tag (gtag.js) - Google Analytics