1.什么是元类
元类让你来定义某些类是如何被创建的,从根本上说,赋予你如何创建类的控制权。可以把元类想成是一个类中类,或是一个类,它的实例是其它的类。当某个类调用type()函数时,你就会看到它到底是谁的实例。
>>> class C(object):
pass
 
>>> class CC:
pass
 
>>> type(C)
<type 'type'>
>>> type(CC)
<type 'classobj'>
>>> import types
>>> type(CC) is types.ClassType
True
2.什么时候使用元类
元类一般用于创建类。在执行类定义时,将检查此类正确的元类,元类通常传递三个参数:类名、从基类继承数据的元组和类的属性字典。
使用class语句定义新类时,解释器执行类的整个主体并填充字典。一旦字典填充完毕,就会被传递给元类构造函数,以创建相应的类对象。
在执行类定义时,解释器必须要知道这个类的正确的元类。
首先,类可以显式地指定其元类,这通过设置__metaclass__类变量来实现:
class Foo:
      __metaclass__ = type
在Python3中,使用下面的语法(在基类元组中提供metaclass关键字参数):
class Foo(metaclass=type)
如果没有显式指定元类,class语句将检查基类元组(如果存在)中的第一个条目。在这种情况下,元类与第一个基类的类型相同。所以,在编写以下内容时,Foo的类类型将与object相同。
class Foo(object):pass
如果没有指定基类,class语句将检查全局变量__metaclass__是否存在。如果找到了该变量,将使用它来创建类。
__metaclass__ = type
class Foo:
      pass
最后,如果没有找到任何__metaclass__值,Python将使用默认的元类。在Python2中,默认的元类是types.ClassType(旧样式类),在Python3中,默认的元类就是type()。
3.谁在使用元类
元类的最终使用者不是用户,正是程序员自己。你可以通过定义一个元类来“迫使”程序员按照某种方式实现目标类,这既可以简化他们的工作,也可以使所编写的程序更符合特定标准。
4.元类何时被创建
创建的元类用于改变类的默认行为和创建方式。创建一个新风格的类或传统类的做法是使用系统自己所提供的元类的默认方式。
自定义元类时,它通常会继承自type(),并重新实现__init__()或__new__()方法。
5.技巧
显式选择元类的最常用技巧是首先定义一个基类,该基类然后用作要被归档的所有对象的父类。例如:
class Documented:
      __metaclass__ = DocMeta#Docmeta是已定义的基类
在Python3中,使用下面的语法(在基类元组中提供metaclass关键字参数):
class Documented(metaclass=DocMeta)
 
class Foo(Documented):
      spam(self,a,b):
          'spam does something'
          pass
元类示例1:用元类创建类时,显示时间标签:
from time import ctime
 
print '***Welcome to Metaclasses!'
print '\tMetaclasses declaration first.'
 
class MetaC(type):
def __init__(cls,name,bases,attrd):
super(MetaC,cls).__init__(name,bases,attrd)
print '***Created class %r at: %s' % (name,ctime())
 
print '\tClass "Foo" declaration next.'
 
class Foo(object):
__metaclass__ = MetaC
def __init__(self):
print '***Instantiated class %r at: %s' %(self.__class__.__name__,ctime())
 
print '\tClass "Foo" instantiation next.'
f = Foo()
print '\tDONE'
执行后输出:
***Welcome to Metaclasses!
Metaclasses declaration first.
Class "Foo" declaration next.
***Created class 'Foo' at: Thu May 30 11:22:35 2013
Class "Foo" instantiation next.
***Instantiated class 'Foo' at: Thu May 30 11:22:35 2013
DONE
元类示例2:创建一个元类,要求程序员在他们写的类中提供一个__str__()方法的实现。如果你还没有在类中覆盖__repr__()方法,元类会给出警告,提示你这么做。如果未实现__str__()方法,将引发一个TypeError的异常。
from  warnings import warn
 
class ReqStrSugRepr(type):
def __init__(cls,name,bases,attrd):
super(ReqStrSugRepr,cls).__init__(name,bases,attrd)
if '__str__' not in attrd:
raise TypeError('Class requires overriding of __str__()')
if '__repr__' not in attrd:
warn('Class suggests overriding of __repr__()\n',stacklevel = 3)
 
print '***Defined ReqStrSugRepr (meta)class\n'
 
class Foo(object):
__metaclass__ = ReqStrSugRepr
def __str__(self):
return 'Instance of class:',self.__class__.__name__
def __repr__(self):
return self.__class__.__name__
 
print '***Defined Foo class\n'
 
class Bar(object):
__metaclass__ = ReqStrSugRepr
def __str__(self):
return 'Instance of class:',self.__class__.__name__
 
print '***Defined Bar class\n'
 
class FooBar(object):
__metaclass__ = ReqStrSugRepr
 
print '***Defined FooBar class\n'
我们编写了三个关于元类的示例,其中一个(Foo)重载了特殊方法__str__()和__repr__(),另一个(Bar)只实现了特殊方法__str__(),还有一个都没有实现,这种情况是错误的。执行此脚本后,我们得到如下输出:
***Defined ReqStrSugRepr (meta)class
 
***Defined Foo class
 
 
Warning (from warnings module):
  File "C:\Python27\lib\idlelib\run.py", line 298
    exec code in self.locals
UserWarning: Class suggests overriding of __repr__()
 
***Defined Bar class
 
 
Traceback (most recent call last):
  File "C:\Documents and Settings\Administrator\桌面\meta.py", line 29, in <module>
    class FooBar(object):
  File "C:\Documents and Settings\Administrator\桌面\meta.py", line 7, in __init__
    raise TypeError('Class requires overriding of __str__()')
TypeError: Class requires overriding of __str__()
需要注意的是我们并没有创建任何测试类的实例,这些类本身就是元类的实例。

Python中的元类和__metaclass__的更多相关文章

  1. Python中的元类(metaclass)

    推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...

  2. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

  3. 深刻理解Python中的元类metaclass(转)

    本文由 伯乐在线 - bigship 翻译 英文出处:stackoverflow 译文:http://blog.jobbole.com/21351/ 译注:这是一篇在Stack overflow上很热 ...

  4. 深刻理解Python中的元类(metaclass)

    译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...

  5. [转] 深刻理解Python中的元类(metaclass)

    非常详细的一篇深入讲解Python中metaclass的文章,感谢伯乐在线-bigship翻译及作者,转载收藏. 本文由 伯乐在线 - bigship 翻译.未经许可,禁止转载!英文出处:stacko ...

  6. Python中的元类

    从前面"Python对象"文章中了解到,在Python中一切都是对象,类可以创建实例对象,但是类本身也是对象. class C(object): pass c = C() prin ...

  7. 深刻理解Python中的元类(metaclass)【转】

    译注:这是一篇在Stack overflow上很热的帖子.提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自省有关,但仍然觉得 ...

  8. 深刻理解Python中的元类(metaclass)以及元类实现单例模式

    在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍 ...

  9. Python中的元类(译)

    add by zhj: 这是大stackoverflow上一位小白提出的问题,好吧,我承认我也是小白,元类这块我也是好多次想搞明白, 但终究因为太难懂而败下阵来.看了这篇文章明白了许多,再加下啄木鸟社 ...

随机推荐

  1. mssql 置疑的处理

    declare @dbName sysName ALTER DATABASE @dbName SET EMERGENCY ALTER DATABASE @dbName SET SINGLE_USER ...

  2. js验证表单大全

    js验证表单大全 1. 长度限制 <script> function test() { if(document.a.b.value.length>50) { alert(" ...

  3. android JSON 技术

    json 语法检查和在线解析网址:http://json.parser.online.fr/ limengwe android Json解析详解(详细代码) http://blog.csdn.net/ ...

  4. 2016/09/21 java关键字static

    1.static方法     static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上th ...

  5. Linux之uboot分析与移植20160601

    说一下uboot分析与移植: 1.下载.建立source insight工程.编译.烧写.如果无运行分析原因 tar xjf u-boot-2012.04.01.tar.bz2 cd u-boot-2 ...

  6. oracle 日志文件管理

    OS: [root@b28-122 ~]# more /etc/oracle-releaseOracle Linux Server release 5.7 DB: SQL> select * f ...

  7. hdu 5233 Gunner II

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5233 简单题,stl水之... #include<algorithm> #include& ...

  8. Knockout应用开发指南 第一章:入门

    2011-11-21 14:20 by 汤姆大叔, 20165 阅读, 17 评论, 收藏,  编辑 1    Knockout简介 (Introduction) Knockout是一个轻量级的UI类 ...

  9. mac 系统开发android,真机调试解决方案

    1.确保你的android设备真正链接到电脑上了,我在这里遇到过坑,弄了好久,才发现能充电的线,确无法传递数据过去.所以不要以为随便拿一根线,能充电,就可以传递数据了,我就是这么傻傻的拿了根不能用的数 ...

  10. 2015年iOS测试现状

    本文由 伯乐在线 - nathanw 翻译,dopcn 校稿.未经许可,禁止转载! 英文出处:www.mokacoding.com.欢迎加入翻译小组. 几周前,我决定将将我在 mokacoding 上 ...