Como chamar uma propriedade da classe base se esta propriedade está sendo substituído na classe derivada?

StackOverflow https://stackoverflow.com/questions/1021464

Pergunta

Eu estou mudando algumas classes de meus de um extenso uso de getters e setters para um uso mais Python de propriedades.

Mas agora eu estou preso porque alguns dos meus getters ou setters anteriores iria chamar o método correspondente da classe base, e em seguida, executar outra coisa. Mas como isso pode ser conseguido com propriedades? Como chamar o getter propriedade ou setter na classe pai?

É claro que apenas chamando o próprio atributo dá recursão infinita.

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
Foi útil?

Solução

Você pode pensar que você poderia chamar a função de classe base que é chamado por propriedade:

class FooBar(Foo):

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

Embora esta é a coisa mais óbvia a tentar Eu acho - Não funciona porque bar é uma propriedade, não um que pode ser chamado

.

Mas a propriedade é apenas um objeto, com um método getter para encontrar o atributo correspondente:

class FooBar(Foo):

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

Outras dicas

Super deve fazer o truque:

return super().bar

Em Python 2.x você precisa usar o mais detalhado sintaxe:

return super(FooBar, self).bar

Há uma alternativa usando super que não requer para se referir explicitamente o nome da classe base.

Classe base 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

Em B, acessando a propriedade getter da classe pai A:

Como outros já respondeu, é:

super(B, self).prop

Ou em Python 3:

super().prop

Isso retorna o valor retornado pelo getter da propriedade, não o próprio getter, mas é suficiente para estender o getter.

Em B, acessando o setter propriedade da classe pai A:

A melhor recomendação que eu tenho visto até agora é a seguinte:

A.prop.fset(self, value)

Eu acredito que este é o melhor:

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

Neste exemplo ambas as opções são equivalentes, mas usando Super tem a vantagem de ser independente das classes de base de B. Se B foram para herdar de uma classe C também estender a propriedade, você não teria de código de atualização do B.

código completa de B estendendo a propriedade de A:

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)

Uma ressalva:

A menos que sua propriedade não tem um setter, você tem que definir tanto o setter e getter em B mesmo se você só mudar o comportamento de um deles.

try

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

Embora eu não tenho certeza se suportes python chamando a propriedade classe base. A propriedade é realmente um objeto que pode ser chamado, que é configurado com a função especificada e, em seguida, substitui o nome da classe. Isto poderia facilmente significar que não há nenhuma função de super disponível.

Você pode sempre mudar a sua sintaxe para utilizar a função de propriedade () que:

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
    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()

(que é a menos que eu estou faltando alguma coisa de sua explicação)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top