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. 【原】简述使用spark集群模式运行程序

    本文前提是已经正确安装好scala,sbt以及spark了   简述将程序挂载到集群上运行的步骤: 1.构建sbt标准的项目工程结构: 其中: ~/build.sbt文件用来配置项目的基本信息(项目名 ...

  2. linux设备驱动层次

    USB 采用树形拓扑结构,主机侧和设备侧的USB 控制器分别称为主机控制器(HostController)和USB 设备控制器(UDC),每条总线上只有一个主机控制器,负责协调主机和设备间的通信,而设 ...

  3. debian完整部署 Nginx + uWSGI + Django

    手工部署一个Django服务器真心不容易,需要安装很多东西.从头开始搭建服务器,主要是为了梳理一下后续开发中一般为碰到的平台部署.对后续问题的解决有一定帮助. 通常部署有2中方式: 一种是使用现成提供 ...

  4. NE、EQ等比较操作符的意义

    比较所有的 字段类型 要比较所有 的字段类型 ,可以在逻 辑表达式中 使用下列运 算符: <运算符>含 义 EQ 等于 = 等于 NE 不 等于 <> 不 等于 >< ...

  5. XAML特殊字符

    此部分只限制在XAML中,代码中不受此类限制. 1.特殊字符转义 XAML 特殊字符转义 特殊字符 转义 小于号 < < 大于号 > > 取址符 & & 引号 ...

  6. Swift计算文本宽高

    iOS 8 开始可以配合 AutoLayout 自动估算文本的高度,但是当 Cell 比较复杂的时候,还会需要手动去计算.首先声明一个样式 var TextStyle : [String : NSOb ...

  7. flask中文问题

    在使用flask时在模板中使用了中文,运行的时候遇到下面的问题: UnicodeDecodeError UnicodeDecodeError: 'utf8' codec can't decode by ...

  8. 44.do文件格式

    style1: transcript onif {[file exists rtl_work]} {<span style="white-space:pre"> < ...

  9. 0-N背包为题(动态规划算法)

    /****************0-N背包问题****************** * 有n个物体装入容量为c的背包,每一个物体有一个体积 * 和一个价值,所装入的物体体积之和不大于背包体积, * ...

  10. 软件工程实践小队--团队项目NABC

    团队项目的NABC 1) N (Need 需求) 作为一个网上教学问答系统,用户的基本需求很明确,即为:提问.搜索.浏览.回答.编辑.评论.附加需求还有: 获取金币.提升等级. 提问:关于一门学科,用 ...