zoukankan      html  css  js  c++  java
  • Python基础:元类

    一、概述

    Python虽然是多范式的编程语言,但它的数据模型却是 纯面向对象 的。与那些仅在语法层面声称纯OO的编程语言(如Java)相比,Python的这种纯粹性更加深入骨髓。

    在Python的世界里,一切皆为对象:数值序列字典函数模块文件类实例 等等,无一例外(参考 Data model)。其中,“类也是对象” 的概念最让人匪夷所思,这完全超越了传统的OO思想。

    元类(metaclass)是Python 2.2中引入的概念,利用元类可以 定制类的创建行为Customizing class creation)。“元类” 的概念同样让人难以理解,然而理解 “元类” 是理解 “类也是对象” 的关键。

    二、经典阐述

    对于元类的理解,目前为止,最经典的阐述莫过于Stack Overflow上面的这篇帖子 What is a metaclass in Python?,e-satis 神一般的回复让人醍醐灌顶,看完后基本就了然于胸了。

    如果觉得看英文比较吃力,这里有一篇中文译版 深刻理解Python中的元类(metaclass)(注:英文原版最近有更新,但核心内容不变)。

    三、核心总结

    1、类的创建过程

    对于类定义:

    class Foo(Base):
        def say(self):
            print 'hello'
    

    Python解释器 执行class语句 时,处理步骤如下:

    1. 确定元类mcls。元类的查找优先级为:

      • 首先查找 类Foo 是否拥有属性__metaclass__
      • 否则查找 类Foo的父类 是否具有属性__metaclass__
      • 否则查找 类Foo所在模块 是否具有全局变量__metaclass__
      • 否则使用默认元类(经典类:types.ClassType;新式类:type
    2. 使用元类mcls创建类Foo。创建语意等价于:

      def say(self):
          print 'hello'
      
      # 元类的参数:mcls(name, bases, dict)
      Foo = mcls('Foo', (Base,), {'say': say})
      
    3. 创建成功后,类Foo 是 元类mcls实例

    综上:创建类 其实是一种更高级别的 实例化过程,本质上与 创建类实例 相似。

    实例化过程 实例 语意形式
    创建类Foo 元类mcls 类Foo class Foo: pass <=> Foo = mcls('Foo', (), {})
    创建类实例foo 类Foo 类实例foo foo = Foo()

    2、元类的使用惯例

    原则上,元类可以是:任何接受参数 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、默认行为

    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
    

    2、使用元类

    为所有类打上作者标签:

    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元类仅有的一点印象。纸上得来终觉浅,绝知此事要躬行,开始吧。

  • 相关阅读:
    将数字转换千分位分隔形式
    根据字符分割字符串的三种写法
    取出字符串中的汉字、字母或是数字
    生成n位随机字符串
    python中类的继承
    汇编语言与计算机体系结构
    DMA(direct memory access)直接内存访问
    数学归纳法证明时间复杂度
    具体名词的理解、单词的深意
    python的类和对象
  • 原文地址:https://www.cnblogs.com/russellluo/p/3409602.html
Copyright © 2011-2022 走看看