【问题标题】:Python __super black magic failedPython __super 黑魔法失败了
【发布时间】:2016-12-05 01:55:20
【问题描述】:

我想为元类创建的每个类添加一个属性。例如,当创建一个名为C 的类时,我想添加一个属性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 时避免“硬编码”类名:

这里的想法是将未绑定的超级对象用作私有对象 属性。例如,在我们的示例中,我们可以定义私有 属性__sup 在类C 中作为未绑定的超级对象 super(C):

>>> C._C__sup = super(C)

在方法中使用此定义,语法self.__sup.meth 可以用作super(C, self).meth 的替代品。优势 是你避免在调用中重复类名 语法,因为该名称隐藏在 private 的修饰机制中 名字。 __sup属性的创建可以隐藏在一个 元类并自动生成。所以,这一切似乎都有效:但是 其实不是这样的。

【问题讨论】:

    标签: python python-2.7 attributes metaclass descriptor


    【解决方案1】:

    使用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 参与到类层次结构中 可能需要super 才能正确调用__init__s 链。这似乎 特别合适,因为您正在构建一个元类来协助 使用super

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      • 2021-12-14
      相关资源
      最近更新 更多