Python __super 黑魔法失败

Python __super black magic failed

我想为元class 创建的每个class 添加一个属性。例如,当创建一个名为 C 的 class 时,我想添加一个属性 C._C__sup ,其值为描述符 super(C).

这是我试过的方法:

class Meta(type):
    def __init__(cls, name, bases, dict): # Not overriding type.__new__
        cls.__dict__['_' + name + '__sup'] = super(cls)
        # Not calling type.__init__; do I need it?

class C(object):
    __metaclass__ = Meta

c = C()
print c._C__sup

这给了我:

TypeError: Error when calling the metaclass bases
    'dictproxy' object does not support item assignment

一些背景信息:
(您不必阅读此部分)

受到this article的启发,我正在做的是在使用super时尽量避免"hardcoding" class名称:

The idea there is to use the unbound super objects as private attributes. For instance, in our example, we could define the private attribute __sup in the class C as the unbound super object super(C):

>>> C._C__sup = super(C)

With this definition inside the methods the syntax self.__sup.meth can be used as an alternative to super(C, self).meth. The advantage is that you avoid to repeat the name of the class in the calling syntax, since that name is hidden in the mangling mechanism of private names. The creation of the __sup attributes can be hidden in a metaclass and made automatic. So, all this seems to work: but actually this not the case.

使用 setattr 而不是赋值给 cls.__dict__:

class Meta(type):
    def __init__(cls, name, bases, clsdict): # Not overriding type.__new__
        setattr(cls, '_' + name + '__sup', super(cls))
        super(Meta, cls).__init__(name, bases, clsdict)

class C(object):
    __metaclass__ = Meta
    def say(self):
        return 'wow'

class D(C):
    def say(self):
        return 'bow' + self.__sup.say()

c = C()
print(c._C__sup)
# <super: <class 'C'>, <C object>>
d = D()
print(d.say())

打印

bowwow

顺便说一句,打电话是个好主意

        super(Meta, cls).__init__(name, bases, clsdict)

Meta.__init__ 中允许 Meta 参与 class 层次结构 可能需要 super 才能正确调用 __init__ 链。这似乎 特别合适,因为您正在构建一个 metaclass 来协助 使用 super.