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. mysql 导入导出数据库、数据表

    Linux下 均在控制台下操作. 导入数据库: 前提:数据库和数据表要存在(已经被创建) (1)将数据表 test_user.sql 导入到test 数据库的test_user 表中 [root@te ...

  2. C#发送邮件源码

    介绍 SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式.SMTP协议属于TCP/IP协议 ...

  3. SQLite数据库管理的相关命令

    1.创建数据库 启动命令行,通过输入如下命令打开Shell模式的CLP: sqlite3 test.db 虽然我们提供了数据库名称,但如果该数据库不存在,SQLite实际上就未创建该数据库,直到在数据 ...

  4. Python自然语言工具包(NLTK)入门

    在本期文章中,小生向您介绍了自然语言工具包(Natural Language Toolkit),它是一个将学术语言技术应用于文本数据集的 Python 库.称为“文本处理”的程序设计是其基本功能:更深 ...

  5. SQLserver使用映射表进行数据相关操作

    基本需求: 老数据有老数据的顺序编码规则,新数据有新数据的顺序编码规则,但是老数据的编码还是要更新相应的东西,新数据也得实时更新,在新数据中已经用新编码规则对老数据对进行编码,在上报表中既要新增新数据 ...

  6. android-监听网络状态

    1.注册一个广播接收器,监听网络状态private void Start() { IntentFilter filter = new IntentFilter(); filter.addAction( ...

  7. VS2010遇到_WIN32_WINNT宏定义问题

    最近拿到一个别人的工程,是使用VS.net创建的,而我的机器上只有vs2010,于是用自带的转换工具将它转换成vs2010的工程,转换之前我就很担心,怕转换完后会出问题,但是没有办法,我实在是不想再安 ...

  8. linux调整分区大小

    查看一下当前分区情况 1 2 3 4 5 6 7 8 [root@localhost ~]# df -h Filesystem            Size  Used Avail Use% Mou ...

  9. 一位iOS教育类应用开发者是如何赚到60多万美元?

    注:伯乐在线12月19日在@程序员的那些事 微博推荐了此文的英文原文,非常感谢@dotSlash 的翻译.  转眼距我写<我如何在iOS教育类应用中赚到20万美元>这篇博文已经一年多了,它 ...

  10. NPOI导出Excel文件,对单元格的一些设置

    HSSFWorkbook book = new HSSFWorkbook(); MemoryStream ms = new MemoryStream(); ISheet sheet = book.Cr ...