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__ для отладки его надо поменять обратно на то, как у тебя было)

Что ты пытался сделать с супер?

Другие вопросы по тегам