2011-10-31 75 views
5

阅读优秀SO post后,我尝试制作一个模块级的元类:的Python元类和对象的基类

def metaclass(future_class_name, future_class_parents, future_class_attrs): 
    print "module.__metaclass__" 
    future_class_attrs["bar"]="bar" 
    return type(future_class_name, future_class_parents, future_class_attrs) 

__metaclass__=metaclass 


class Foo(object): 

    def __init__(self): 
     print 'Foo.__init__' 

f=Foo() 

这不工作(即“模块元类”没有得到印)除非我删除了Foo的object基类。怎么来的?

注意:我正在使用Python 2.6.1。

回答

3

继承自对象自动将类型元类与它一起。这会覆盖您的模块级别__metaclass__规范。

如果在类级别指定元类,然后对象不会覆写:

def metaclass(future_class_name, future_class_parents, future_class_attrs): 
    print "module.__metaclass__" 
    future_class_attrs["bar"]="bar" 
    return type(future_class_name, future_class_parents, future_class_attrs) 

class Foo(object): 
    __metaclass__ = metaclass 

    def __init__(self): 
     print 'Foo.__init__' 

f=Foo() 

参见http://docs.python.org/reference/datamodel.html?highlight=metaclass#customizing-class-creation

+0

规范说没有这样的事情。它所说的是,如果存在基类,则将使用基类的元类,而不管基类是否指定元类。 – Marcin

2

说明书specifies the order in which Python will look for a metaclass

适当的元类由以下优先级决定 规则:

  • 如果存在dict['__metaclass__'],则使用它。
  • 否则,如果在 至少有一个基类,则使用其元类(首先查找 __class__属性,如果未找到,则使用其类型)。
  • 否则,如果存在名为__metaclass__的全局变量,则使用它。
  • 否则,使用旧式经典元类(types.ClassType)。

你会从根本上面,有一个基类看(无论基类,即使它不最终从object继承)抢占了模块级__metaclass__