Eu pesquisei sobre isso há um tempo, mas sempre encontrei respostas como "você tem que usar a referencia de self
para acessar os atributos de instância da classe". Estou assumindo que o seu código é parecido com o que está abaixo, quando inclui a classe Programa
:
class Programa(object):
def __init__(self, nome, ano):
self._nome = nome
self._ano = ano
class Filme(Programa):
def __init__(self, nome, ano, duracao):
super().__init__(nome, ano)
self.duracao = duracao
def oi(self):
return self._nome
if __name__ == '__main__':
f = Filme('Escola de Rock', 2008, 2)
print(f.oi())
Como a resposta que encontrei funcionava, mas não entendia exatamente pq super()._nome
, olhei na documentação e encontrei 2 coisas:
1) Variáveis de classe e variáveis de instancias. No primeiro caso a variável é compartilhada com todas as instâncias da classe. No segundo caso, a variável é única para cada instância. (https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables). Então eu assumi que a variável (como em nosso exemplo) nome
, pertence à instância que está sendo criada.
2) ainda assim, parece confuso, mas olha o que fala a documentação de super()
: "Retorna um objeto proxy (um objeto intermediário) que delega as chamadas de METODO
para a classe pai" (https://docs.python.org/3.3/library/functions.html#super). Assim, assumi que super()
vai nos ligar com os métodos da classe pai, e para acessar os atributos, precisamos acessar via self
, pq esses atributos estão ligados à instância criada (da classe filha).
Testando a hipótese de que o objeto proxy, gerado por super()
consegue acessar o atributo _nome
. Vamos criar um método que retorna o nome na classe Programa
:
class Programa(object):
def __init__(self, nome, ano):
self._nome = nome
self._ano = ano
def nome_encapsulado_na_classe_base(self):
return self._nome
class Filme(Programa):
def __init__(self, nome, ano, duracao):
super().__init__(nome, ano)
self.duracao = duracao
def oi(self):
return super().nome_encapsulado_na_classe_base()
if __name__ == '__main__':
f = Filme('Escola de Rock', 2008, 2)
print(f.oi())
Extra: sim é possível termos uma sintaxe como super()._nome
(no exemplo abaixo super()._ano). Mas mantenha esse exemplo somente como curiosidade, pois não é um design legal. E quando vc chegar na parte de propriedades (encapsulamento), vai entender, que o mecanismo é o mesmo que o do exemplo anterior [proxy object que delega chamadas de métodos], porém com um syntax sugar:
class Programa(object):
def __init__(self, nome, ano):
self._nome = nome
self.__ano = ano
def nome_encapsulado_na_classe_base(self):
return self._nome
@property # além de encapsular a variável ano, vai nos dar a sintaze `meu_obj._ano`, sem a necessidade de usar os parenteses
def _ano(self):
return self.__ano
class Filme(Programa):
def __init__(self, nome, ano, duracao):
super().__init__(nome, ano)
self.duracao = duracao
def oi(self):
return super().nome_encapsulado_na_classe_base()
def ano_filme(self):
return super()._ano
if __name__ == '__main__':
f = Filme('Escola de Rock', 2008, 2)
print(f.oi())
print(f.ano_filme())