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

  • 相关阅读:
    The formatter threw an exception while trying to deserialize the message in WCF
    通过Web Deploy方式部署WCF
    The Managed Metadata Service or Connection is currently not available
    How to create Managed Metadata Column
    冒泡算法
    asp.net core 实战项目(一)——ef core的使用
    Vue学习笔记入门篇——安装及常用指令介绍
    Vue学习笔记入门篇——数据及DOM
    Vue学习笔记目录
    Chart.js在Laravel项目中的应用
  • 原文地址:https://www.cnblogs.com/russellluo/p/3409602.html
Copyright © 2011-2022 走看看