Python 2.6: Как получить доступ к полю дескриптора базового класса, скрытого производным классом? - PullRequest
3 голосов
/ 17 марта 2011

У меня есть дескриптор, хранящий данные в словаре хост-объекта.И у меня есть поля этого дескриптора в иерархии классов с тем же именем:

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']. set (b, 'a')?


Исправлено:

В форме, указанной в моем первоначальном посте, Af оценивается как свойство с именем по имени ключа (отсутствует) или по умолчанию 8192 - ничего общего с ним.Вот почему я использовал A. dict ['f'] - чтобы исключить get call.Небольшая модификация потребовалась, чтобы позволить 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 Ответ

1 голос
/ 17 марта 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...