2010-07-26 3 views
21

В настоящее время я использую декоратор @property для достижения «геттеров и сеттеров» в нескольких моих классах. Я хочу унаследовать эти методы @property в дочернем классе.Переопределение унаследованных объектов свойств в Python

У меня есть некоторый код Python (в частности, я работаю в py3k), который выглядит неопределенно, как так:

class A: 
    @property 
    def attr(self): 
     try: 
      return self._attr 
     except AttributeError: 
      return '' 

class B(A): 
    @property 
    def attr(self): 
     return A.attr # The bit that doesn't work. 

    @attr.setter 
    def attr(self, value): 
     self._attr = value 

if __name__ == '__main__': 
    b = B() 
    print('Before set:', repr(b.attr)) 
    b.attr = 'abc' 
    print(' After set:', repr(b.attr)) 

Я отмеченную часть, которая не работает с комментарием. Я хочу, чтобы getter getter базового класса возвращался. A.attr возвращает объект недвижимости (который, вероятно, очень близок к тому, что мне нужно!).

Edit:
После получения ответа от Ned ниже я придумал, что я думаю, что это более элегантное решение этой проблемы.

class A: 
    @property 
    def attr(self): 
     try: 
      return self._attr 
     except AttributeError: 
      return '' 

class B(A):   
    @A.attr.setter 
    def attr(self, value): 
     self._attr = value 

if __name__ == '__main__': 
    b = B() 
    print('Before set:', repr(b.attr)) 
    b.attr = 'abc' 
    print(' After set:', repr(b.attr)) 

.setter декоратор ожидает объект свойства, которые мы можем получить с помощью @A.attr. Это означает, что нам не нужно снова объявлять свойство в дочернем классе.

(! Это разница между работой над проблемой в конце дня против работать над ней в начале дня)

+0

У меня была такая же проблема, и может подтвердить ваш ответ работает, но WOW то, что $ hitty «особенность» - Добавление суперкласс связи! !! Это плохой дизайн на стороне python. Либо это, либо «переопределить» свойство. Либо дрянные «решения» для наследования. – Marc

ответ

4

Я думаю, что вы хотите:

class B(A): 
    @property 
    def attr(self): 
     return super(B, self).attr 

Вы упоминаете желая вернуть getter родительского класса, но вам нужно вызвать getter, а не вернуть его.

+0

Это не работает для меня, если я назову 'super(). Attr' Я получаю желаемый эффект. Это разумная вещь? – casr

+0

Ах, вы правы, потому что родительский .attr больше не доступен как invokable getter, а только как свойство. super() - это способ доступа к атрибутам с одинаковым именем из родительских классов. Почему это было бы неразумно? –

+0

Просто проверки. У меня не было причины. Обновите свой ответ, чтобы иметь 'super(). Attr' вместо' super (B, self) .attr() ', и я помечаю его как ответ :) Спасибо за подсказку! – casr

23

Чтобы переопределить сеттер в Python 2 я сделал это:

class A(object): 
    def __init__(self): 
     self._attr = None 

    @property 
    def attr(self): 
     return self._attr 

    @attr.setter 
    def attr(self, value): 
     self._attr = value 


class B(A): 
    @A.attr.setter 
    def attr(self, value): 
     # Do some crazy stuff with `value` 
     value = value[0:3] 
     A.attr.fset(self, value) 
+0

Интересно, что 'B' не * имеет * наследовать геттер от' A'. Если 'B' наследуется только от' object', 'B.attr.fget' вернет' '. Я был обеспокоен тем, что 'A.attr.fset' теперь назначена пользовательская функция. 'A.attr.fset' по-прежнему' None', а 'B.attr.fset' -' '. Поэтому, переопределяя любой из элементов доступности свойств, сначала создается копия свойства. По крайней мере, похоже, это то, что происходит. –

+0

Мне особенно нравится, как вы показали, как переопределить только сеттера. Я не знал, как это сделать, и это дает мне немного больше информации о декораторе сеттера. – MrMas

Смежные вопросы