设为首页 收藏本站
查看: 988|回复: 0

[经验分享] Python基础:元类

[复制链接]

尚未签到

发表于 2015-4-24 05:55:06 | 显示全部楼层 |阅读模式

  • 一、概述
  • 二、经典阐述
  • 三、核心总结

    • 1、类的创建过程
    • 2、元类的使用惯例


  • 四、简单案例

    • 1、默认行为
    • 2、使用元类


  • 五、实践为王

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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-60029-1-1.html 上篇帖子: 结巴分词 0.27 发布,Python 中文分词组件 下篇帖子: python win32api 使用小技巧
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表