简体   繁体   English

Python __超级黑魔法失败

[英]Python __super black magic failed

I want to add an attribute for every class created by a metaclass. 我想为元类创建的每个类添加一个属性。 For example, when a class named C is created, I want add an attribute C._C__sup whose value is the descriptor super(C) . 例如,当创建一个名为C的类时,我想添加一个属性C._C__sup其值为描述符super(C)

Here is what I've tried: 这是我尝试过的:

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

This gives me: 这给了我:

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

Some background information: 一些背景信息:
(You don't have to read this part) (您不必阅读此部分)

Inspired by this article , what I'm doing is trying to avoid "hardcoding" the class name when using super : 本文的启发,我正在尝试避免在使用super时对类名进行“硬编码”:

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的私有属性__sup定义为未绑定的超级对象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 . 在方法中使用此定义后,语法self.__sup.meth可以替代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. __sup属性的创建可以隐藏在元类中并使其自动进行。 So, all this seems to work: but actually this not the case. 因此,所有这些似乎都起作用:但是实际上并非如此。

Use setattr instead of assignment to cls.__dict__ : 使用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())

prints 版画

bowwow

By the way, it is a good idea to call 顺便说一句,打电话是个好主意

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

inside Meta.__init__ to allow Meta to participate in class hierarchies which might need super to properly call a chain of __init__ s. Meta.__init__内部,以允许Meta参与类层次结构,这可能需要super才能正确调用__init__的链。 This seems particularly appropriate since you are building a metaclass to assist with the use of super . 这似乎特别合适,因为您正在构建一个元类来辅助使用super

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM