我有一个描述符将数据存储在宿主对象的字典中。 我在类层次结构中有这个描述符的同名字段:
class ADescriptor(object):
def __init__(self, keyname='descr'):
self.keyname = keyname
def __get__(self, obj, objtype):
return getattr(obj, self.keyname, 8192 )
def __set__(self, obj, val):
setattr(obj, self.keyname, val)
class A(object):
f = ADescriptor('keyA')
class B(A):
f = ADescriptor('keyB')
b = B()
b.f = 'b'
print super(B,b).f
super(B,b).f = 'a'
最后一行不起作用: super (B,b).f = 'a'
为什么 get 有效而 analogue set 无效? 我可以用比 A.dict['f'].set(b,'a') 更优雅的方式设置 A 的 f 吗?
更正:
在我最初的帖子中给出的表格中,A.f 评估为 A 的以键名命名的属性(缺失)或默认 8192 - 与它无关。这就是为什么我使用 A.dict['f'] - 来排除 get 调用。 需要稍作修改才能将 A.f 评估为所需的 ADescriptor 实例:
def __get__(self, obj, objtype=None):
if not obj: #return descriptor itself if no bound object given
return self
return getattr(obj, self.keyname, 8192 )
在这种情况下 A.f.__set__(b,'a')
有效。
但是还是很丑!
@BiggAl 提供的属性解决方案不适合我的需求 - 我需要将所有描述符包装在属性中。
最佳答案
如果 A.__dict__['f'].__set__(b,'a')
有效,A.f.__set__(b,'a')
肯定会有效吗?
然后甚至 A.f.b = 'a'
也可以工作,尽管如果我没记错的话,您可能必须将其指定为属性。
看历史看脑残...
>>> class ADescriptor(object):
def __init__(self, keyname='descr'):
self.keyname = keyname
def __get__(self, obj, objtype):
return (self.keyname, getattr(obj, self.keyname, 8192 ))
def __set__(self, obj, val):
setattr(obj, self.keyname, val)
>>> class A(object):
f = ADescriptor('keyA')
>>> class B(A):
f = ADescriptor('keyB')
>>> a, b = A(), B()
>>> print (a.f, b.f, A.f, B.f)
(('keyA', 8192), ('keyB', 8192), ('keyA', 8192), ('keyB', 8192))
>>> b.f = 'b'
>>> print (a.f, b.f, A.f, B.f)
(('keyA', 8192), ('keyB', 'b'), ('keyA', 8192), ('keyB', 8192))
>>> A.f = 'a'
>>> print (a.f, b.f, A.f, B.f)
('a', ('keyB', 'b'), 'a', ('keyB', 8192))
>>>
这就是你的理解? (为了调试我改了__get__
,应该改回你原来的样子)
你想用 super 做什么?
关于 python 2.6 : How to access base class descriptor field hidden by derived class?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5336147/