一、概述

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语句 时,处理步骤如下:

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

首先查找 类Foo 是否拥有属性__metaclass__

否则查找 类Foo的父类 是否具有属性__metaclass__

否则查找 类Foo所在模块 是否具有全局变量__metaclass__

否则使用默认元类(经典类:types.ClassType;新式类:type)

使用元类mcls创建类Foo。创建语意等价于:

def say(self):

print 'hello'

# 元类的参数:mcls(name, bases, dict)

Foo = mcls('Foo', (Base,), {'say': say})

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

python元类_Python基础:元类相关推荐

  1. Python学习教程(Python学习路线_Python基础学习教程_Python视频教程):初学者新手怎样快速入门Python

    Python学习教程(Python学习路线_Python基础学习教程_Python视频教程):初学者新手怎样快速入门Python? 人生苦短,我用Python!!!短短几个字,现在在各大学习类平台随处 ...

  2. python内置属性类_Python内置类属性,元类研究

    Python内置类属性 我觉得一切都是对象,对象和元类对象,类对象其实都是一样的,我在最后进行了证明,但是只能证明一半,最后由于元类的父类是type,他可以阻挡对object属性的访问,告终 __di ...

  3. python如何设计工具类_Python基础之自定义工具类

    class ListHelper: @staticmethod def find_all(target, func_condition): """ 查找列表中满足条件的所 ...

  4. python如何定义类_python中定义类

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 类的定义python中,定义类是通过class关键字,例如我们定义一个存储学生信 ...

  5. python的模块和类_Python模块和类.md

    模块的定义 代码的层次结构 对于python的层次结构一般为包->模块 包也就是文件夹,但是文件夹下必须有文件"init.py"那么此文件夹才可以被识别为包."in ...

  6. 命名空间_python基础 13 类命名空间于对象、实例的命名空间,组合方法

    python基础 13 类命名空间于对象.实例的命名空间,组合方法 1.类命名空间于对象.实例的命名空间 创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性 而类有两 ...

  7. python编写ATM类_Python中编写类的各种技巧和方法

    有关 Python 内编写类的各种技巧和方法(构建和初始化.重载操作符.类描述.属性访问控制.自定义序列.反射机制.可调用对象.上下文管理.构建描述符对象.Pickling).你可以把它当作一个教程, ...

  8. list 相加_Python 基础 list类、运算符

    从最初的"Hello World",走到面向对象.该回过头来看看,教程中是否遗漏了什么. 我们之前提到一句话,"Everything is Object". 那 ...

  9. python类_Python中的类

    Python和Java都是面向对象的语言,对象从类中获取,类指的是同一类具有相同特征的事物,比如拉布拉多,柯基,哈士奇,它们都是狗,具有狗的相同特征,所以可以被归为一类Dog,Python中类的使用与 ...

最新文章

  1. 集合啦,NLP数据增强技术!超全资源汇总
  2. 嵌入式系统功能需求分析_超市监控系统的功能作用分析
  3. sphinx 源码阅读之分词,压缩索引,倒排——单词对应的文档ID列表本质和lucene无异 也是外部排序再压缩 解压的时候需要全部扫描doc_ids列表偏移量相加获得最终的文档ID...
  4. studio-引入外来包
  5. 【Qt开发】常用控件--QLineEdit
  6. android 两足机器人,基于Android的双足机器人语音控制系统研究
  7. 如何往eclipse中导入maven项目
  8. 使用jquery操作iframe
  9. Pixazza把每张图片自动变成广告赚钱
  10. HTML知识积累及实践(二) - 标签样式
  11. Google gae部署php简单说明
  12. java用1234组成_java编程题,java1234组成三位数不重复
  13. word实现多级自动编号
  14. 杜立特尔分解法 MATLAB,chase追赶法算法
  15. 设置font标签居中显示
  16. java BBS论坛
  17. usemvc永远不会被使用_你永远不会离开
  18. PHP 实现word在线预览
  19. 网络设备流量及性能监控的实现
  20. 基于Dragonboard 410c的PMIC简介

热门文章

  1. python中的数据分析库有哪些_五大常用数据科学Python库
  2. 解决npm install时的一系列gyp ERR错误
  3. POJ 1655 Balancing Act
  4. oracle10显示数据库错误,Oracle10gR2数据库出现ORA-3136错误的解决方法
  5. 在状态栏StatusBar中添加网速实时显示
  6. u深度制作linux启动盘制作工具,u深度u盘启动盘制作工具教程
  7. vue + html2canvas + ArcGIS 3.x 地图一键截图功能踩坑之路(一)
  8. Flink入门系列05-时间语义
  9. js自下而上无缝滚动
  10. 智能汽车进入HPC时代,这家本土芯片厂商如何领跑市场