2016-11-13 61 views
0

考虑下面的代码的静态属性:使用元类访问子

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" 

我想要实现的是有功能print_name可以在B子类(C和d)打了个电话,让它会打印名称为的静态属性。所以期望的输出应该看起来像这样 -

animal 
zebra 
pig 

非常感谢!

回答

2

在你print_name()功能,应更换此:

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

与此:

return cls 

这种方式,你会摆脱TypeError你看到的。

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

现在,即使使用此修复程序,您也不会在输出中看到“斑马纹”和“猪”,因为您直接从type生成类B,这样您的元类信息就会丢失。

你应该考虑这样的事情:

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型的,你的代码将在每次创建一个子类时被正确执行。

(作为一个方面说明,元类可以使不可能使用多重继承,所以仔细考虑是否真的需要它们。)