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's f более элегантно, чем A.dict['f'].установить(б, "а")?
Исправленный:
В форме, приведенной в моем первоначальном посте, Af оценивает свойство с именем ключа по имени A (отсутствует) или по умолчанию 8192 - не имеет к этому никакого отношения. Вот почему я использовал A.dict['f'] - чтобы исключить получение вызова. Небольшая модификация потребовалась, чтобы позволить Af быть оцененным в необходимый экземпляр 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 ответ
Конечно A.f.__set__(b,'a')
будет работать, если A.__dict__['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__
для отладки его надо поменять обратно на то, как у тебя было)
Что ты пытался сделать с супер?