Python 2.6:如何访问被派生类隐藏的基类描述符字段?
我有一个描述符,它把数据存储在主对象的字典里。这个描述符在类的层次结构中有一些同名的字段:
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'
为什么获取值的操作可以,而设置值的操作不行呢?有没有比用 A.dict['f'].set(b,'a') 更优雅的方法来设置 A 的 f 呢?
更正:
在我最初的帖子中,A.f 的值是 A 的一个名为 keyname 的属性(缺失)或者默认值 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 提出的属性解决方案不适合我的需求 - 我需要把所有的描述符都包装成属性。
1 个回答
1
当然,如果 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 做什么呢?