使用元类来访问子类的静态属性

时间:2016-11-13 22:29:40

标签: python metaclass

考虑以下代码:

def print_name(*args, **kwargs):

    cls = type(*args, **kwargs)
    print "hello " + cls.name
    return type.__new__( *args, **kwargs)

class B(object):
    __metaclass__ = print_name
    name = 'animal'

class C(B):
    name = "zebra"

class D(B):
    name = "pig"

我想要实现的是在B子类(C和D)上调用函数 print_name 并使其打印静态属性 name 。所以期望的输出应该如下所示 -

animal
zebra
pig

非常感谢!

1 个答案:

答案 0 :(得分:2)

print_name()函数中,您应该替换它:

return type.__new__( *args, **kwargs)

用这个:

return cls

这样你就可以摆脱你所看到的TypeError

发生错误是因为__new__的第一个参数必须是类型对象。 __new__的正确调用是:type.__new__(type, *args, **kwargs),但在您的情况下,确实没有必要两次创建类。

现在,即使使用此修复程序,您也不会在输出中看到'zebra'和'pig',因为您直接从B生成了类type,因此您的元类信息丢失了。

你应该考虑这样的事情:

class print_name(type):

    def __new__(mcls, *args, **kwargs):
        cls = super(print_name, mcls).__new__(mcls, *args, **kwargs)
        print "hello " + cls.name
        return cls

这样,B及其所有子类的类型为print_name,每次创建子类时都会正确执行代码。

(作为旁注,元类可能使得无法使用多重继承,因此请仔细考虑是否真的需要它们。)