Python __super 黑魔法失败了
Posted
技术标签:
【中文标题】Python __super 黑魔法失败了【英文标题】:Python __super black magic failed 【发布时间】: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
属性的创建可以隐藏在一个 元类并自动生成。所以,这一切似乎都有效:但是 其实不是这样的。
【问题讨论】:
【参考方案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
。
【讨论】:
以上是关于Python __super 黑魔法失败了的主要内容,如果未能解决你的问题,请参考以下文章