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. Laravel 5 基础(九)- 表单

    首先让我们修改路由,能够增加一个文章的发布. Route::get('articles/create', 'ArticlesController@create'); 然后修改控制器 public fu ...

  2. UCOS2_STM32F1移植详细过程(四)

    Ⅰ.概述 上一篇文章是讲述uC/OS-II Ports下面os_cpu_a.asm.os_cpu_c.c和os_cpu.h文件底层端口代码的移植(修改)和说明,接着上一篇文章来讲述关于UCOS移植应用 ...

  3. 解决在sublime text3在ubuntu下无法输入中文的问题

    方法链接:https://github.com/lyfeyaj/sublime-text-imfix 效果图:

  4. SQL语句基础之 单表查找

    Sql语句之 单表查询 一.一般查询 1.查看表中的所有记录 以及 所有字段(属性) 语句 : select * from student; 2.只查看某些字段 语句:select sname,sex ...

  5. NOJ1142-最大连续和

    最大连续和 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 1282            测试通过 : 230 ...

  6. chrome下的js调试

    console输出对象信息:console.log(object[,object,.....])

  7. Spring框架中的IOC和DI的区别

    上次面试被问到IOC和DI的区别时,没怎么在意,昨天又被问到,感觉有点可惜.今晚总算抽点时间,查看了spring官方文档.发现,IoC更像是一种思想,DI是一种行为.为了降低程序的耦合度,利用spri ...

  8. mvc中使用knockoutjs和ajax

    虽然说knockoutjs 官网上写的非常的清楚!但是像我这样的英语呕吐患者,真是虐心啊!今天我写下做个记录,也为那些初次使用的同学给予帮助, 首先我说一下今天我说的内容只是应用不做原理探究,如果没有 ...

  9. 数据持久化-Plist文件写入

    数据持久化,常见4种:归档,plist文件,sqlite,coreData.今天复习的是plist文件读写. // // ViewController.m // Test_Plist // // Cr ...

  10. 第三方登录开发-Facebook

    这次这个项目要分别可以使用新浪微博,qq互联以及Facebook和Twitter授权登录 facebook目前只支持oauth2技术,个人理解其工作流程是当用户想访问当前网站,却不想注册账号,此时当前 ...