Python元类和对象基类

6 投票
2 回答
3810 浏览
提问于 2025-04-17 05:21

在阅读了那篇很棒的StackOverflow帖子后,我尝试创建一个模块级的 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)

__metaclass__=metaclass


class Foo(object):

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

f=Foo()

这段代码不工作(也就是说,“module.metaclass”没有被打印出来),除非我去掉 Foo 的 object 基类。为什么会这样呢?

注意:我使用的是 Python 2.6.1。

2 个回答

2

这个说明文档讲述了Python查找元类的顺序

合适的元类是根据以下优先级规则来决定的:

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

从上面的内容可以看出,只要有一个基类存在(不管这个基类是什么,即使它最终不继承自object),就会优先使用模块级的__metaclass__

3

object 继承会自动带上 type 这个元类。这会覆盖你在模块级别上指定的 __metaclass__

如果在类级别指定了元类,那么 object 就不会覆盖它:

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

撰写回答