如何堆栈元类

时间:2017-12-23 15:41:41

标签: python python-2.x metaclass

我想" stack"元类。

def dec(cls):
    class newmeta(cls.__metaclass__):
        def __call__(cls, *args, **kwargs):
            obj = cls.__metaclass__.__call__(cls, *args, **kwargs)
            obj.x *= 2 #this happens AFTER __init__ is called
    cls.__metaclass__ = newmeta
    return cls

@dec
@dec
class Foo(object):
    def __init__(self, x):
        self.x = 5

print Foo().x #expect 20

但是,我似乎无法以这种方式访问​​Foo.__metaclass__ ....实际上("__metaclass__" in Foo.__dict__) == False

怎么会这样呢?

2 个答案:

答案 0 :(得分:2)

Alter existsing cls.__metaclass__没有效果,因为元类确定了类的构建方式,你必须用你的元类创建一个新的类对象:

def dec(cls):
    basetype = type(cls)
    class newmeta(basetype):
        def __call__(cls, *args, **kwargs):
            obj = super(newmeta, cls).__call__(*args, **kwargs)
            obj.x *= 2
            return obj
    new_cls = newmeta(cls.__name__, cls.__bases__, dict(cls.__dict__))
    return new_cls


@dec
@dec
class Bar(object):

    def __init__(self):
        self.x = 5


o = Bar()
print o.x

的产率:

20

ps:此方法适用于python 2和3。

答案 1 :(得分:0)

如果您正在谈论Python 3.5+,则不再支持__metaclass__,如此处所述 __metaclass__ in Python3.5