Как вызвать свойство базового класса, если это свойство перезаписывается в производном классе?

Я изменяю некоторые мои классы с широкого использования геттеров и сеттеров на более питонное использование свойств.

Но теперь я застрял, потому что некоторые из моих предыдущих получателей или установщиков вызывали соответствующий метод базового класса, а затем выполняли что-то еще. Но как это можно сделать с помощью свойств? Как вызвать свойство getter или setter в родительском классе?

Конечно, просто вызов самого атрибута дает бесконечную рекурсию.

<code>class Foo(object):

    @property
    def bar(self):
        return 5

    @bar.setter
    def bar(self, a):
        print a

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return self.bar # --> recursion!

    @bar.setter
    def bar(self, c):
        # perform the same action
        # as in the base class
        self.bar = c    # --> recursion!
        # then do something else
        print 'something else'

fb = FooBar()
fb.bar = 7
</code>

Ответы на вопрос(5)

Супер должен сделать трюк:

В Python 2.x вам нужно использовать более подробный синтаксис:

return super(FooBar, self).bar
 20 июн. 2009 г., 13:50
супер (MyClass, self) .bar ()
 20 июн. 2009 г., 13:49
TypeError: super () принимает как минимум 1 аргумент (задано 0)
 26 янв. 2014 г., 21:17
Кажется, что super (). bar отлично работает для получателя, но не работает для назначения через свойство base в переопределенном установщике. Если я делаю super (). Bar = 3, я получаю AttributeError: & quot; super & apos; объект не имеет атрибута "bar"
 20 июн. 2009 г., 14:01
Я думаю (ну, судя по ссылке: P), этот ответ связан с python3. В python3 super () может принимать нулевые аргументы, да.
 28 янв. 2014 г., 10:40
Хороший вопрос, Роб, не знал этого. Вот больше информации:stackoverflow.com/questions/10810369/…
Решение Вопроса

что можете вызвать функцию базового класса, которая вызывается свойством:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar(self)

Хотя это самая очевидная вещь, которую стоит попробовать, я думаю -it does not work because bar is a property, not a callable.

Но свойство - это просто объект, с методом получения, чтобы найти соответствующий атрибут:

class FooBar(Foo):

    @property
    def bar(self):
        # return the same value
        # as in the base class
        return Foo.bar.fget(self)
 01 февр. 2016 г., 05:24
Не разрешайте MRO самостоятельно, используйтеsuper.
 06 мар. 2017 г., 21:58
@nerdoc, гдеself получить из цепочкиFoo.bar.fset?
 09 дек. 2013 г., 09:13
Я получаю TypeError: & apos; property & apos; объект не вызывается
 20 июн. 2009 г., 14:10
+1 ... и Foo.bar.fset (self, c) для сеттера
 13 нояб. 2013 г., 20:53
Зачем мне звонитьFoo.bar.fset(self, c) в унаследованном сеттере? Почему бы и нетFoo.bar.fset(c) - без "себя" -Я думал, что это неявно прошло?

super это не требует явной ссылки на имя базового класса.

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

    @property
    def prop(self):
        return self._prop

    @prop.setter
    def prop(self, value):
        self._prop = value

class B(A):
    # we want to extend prop here
    pass
In B, accessing the property getter of the parent class A:

Как уже ответили другие, это:

super(B, self).prop

Или в Python 3:

super().prop

Это возвращает значение, возвращаемое получателем свойства, а не самим получателем, но его достаточно для расширения получателя.

In B, accessing the property setter of the parent class A:

Лучшая рекомендация, которую я видел до сих пор, заключается в следующем:

A.prop.fset(self, value)

Я считаю, что этот лучше

super(B, self.__class__).prop.fset(self, value)

В этом примере оба варианта эквивалентны, но использование super имеет преимущество, заключающееся в независимости от базовых классовB, ЕслиB должны были унаследовать отC Класс также расширяет свойство, вам не придется обновлятьBкод.

Full code of B extending A's property:
class B(A):
    @property
    def prop(self):
        value = super(B, self).prop
        # do something with / modify value here
        return value

    @prop.setter
    def prop(self, value):
        # do something with / modify value here
        super(B, self.__class__).prop.fset(self, value)
One caveat:

Если ваше свойство не имеет установщика, вы должны определить как установщик, так и получатель вB даже если вы измените только поведение одного из них.

 03 окт. 2016 г., 09:24
Это намного понятнее для меня.
 02 нояб. 2018 г., 19:55
Не могли бы вы объяснить, какsuper(B, self.__class__) работает именно сsuper(class, class)? Где это задокументировано?
 30 нояб. 2017 г., 21:16
Здравствуйте, это очень полезно. У меня есть дополнительный вопрос к этому. Эта установка работает хорошо; однако он перестает работать, когда я установилinit для B, чтобы определить дополнительные свойства. Есть ли способ иметь отдельныйinit для Б? Спасибо

пытаться

@property
def bar:
    return super(FooBar, self).bar

Хотя я не уверен, поддерживает ли Python вызов свойства базового класса. Свойство на самом деле является вызываемым объектом, который устанавливается с помощью указанной функции, а затем заменяет это имя в классе. Это может легко означать, что нет супер функции доступны.

Вы всегда можете переключить свой синтаксис на использование функции property ():

class Foo(object):

    def _getbar(self):
        return 5

    def _setbar(self, a):
        print a

    bar = property(_getbar, _setbar)

class FooBar(Foo):

    def _getbar(self):
        # return the same value
        # as in the base class
        return super(FooBar, self)._getbar()

    def bar(self, c):
        super(FooBar, self)._setbar(c)
        print "Something else"

    bar = property(_getbar, _setbar)

fb = FooBar()
fb.bar = 7
 15 янв. 2013 г., 15:02
Это прекрасно работает, если вы пишете базовый класс. Но что, если вы расширяете сторонний базовый класс, который использует одно и то же имя для свойства и метода получения?
    class Base(object):
      def method(self):
        print "Base method was called"

    class Derived(Base):
      def method(self):
        super(Derived,self).method()
        print "Derived method was called"

    d = Derived()
    d.method()

 15 янв. 2013 г., 15:01
Вы: он говорит о свойствах, а не о простых методах

Ваш ответ на вопрос