2016-07-30 52 views
1

我想为元类创建的每个类添加一个属性。例如,创建名为C的类时,我想添加一个属性C._C__sup,其值为描述符super(C)Python __超级黑魔法失败

这里是我试过:

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时避免“硬编码”之类的名字:

的思路是使用未绑定的超级对象作为私人 属性。

>>> C._C__sup = super(C) 

的语法self.__sup.meth 可以作为一种替代的方法,这里面定义:例如,在我们的例子中,我们可以在类C为未绑定的超级对象 super(C)定义私有 属性__supsuper(C, self).meth。 的优点是避免重复调用 语法中类的名称,因为该名称隐藏在私人 名称的加密机制中。 __sup属性的创建可以隐藏在 元类中并自动创建。所以,这一切似乎工作:但 其实并非如此。

回答

2

使用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