如何堆叠元类

How to stack metaclasses

我想要"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

人们会怎么做呢?

如果您谈论的是 Python 3.5+,则不再支持 __metaclass__,如此处所述

A​​lter existing cls.__metaclass__ 无效,因为 metaclass 决定了 class 的构建方式,您必须使用您的 meta[=21] 创建一个新的 class 对象=]:

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。