[英]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 classC
as the unbound super objectsuper(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 tosuper(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.