Herança e substituindo __init__ em python
-
09-09-2019 - |
Pergunta
Eu estava lendo 'Dive Into Python' e no capítulo sobre as classes que dá este exemplo:
class FileInfo(UserDict):
"store file metadata"
def __init__(self, filename=None):
UserDict.__init__(self)
self["name"] = filename
O autor então diz que se você quiser substituir o método __init__
, você deve chamar explicitamente o __init__
pai com os parâmetros corretos.
- E se essa classe
FileInfo
teve mais de uma classe ancestral?- Eu tenho que chamar explicitamente todos os métodos
__init__
as classes ancestrais?
- Eu tenho que chamar explicitamente todos os métodos
- Além disso, eu tenho que fazer isso a qualquer outro método que deseja substituir?
Solução
O livro é um pouco datado com respeito a subclasse-superclasse chamada. É também um pouco datada com respeito a subclasse built-in classes.
Parece que este hoje em dia.
class FileInfo(dict):
"""store file metadata"""
def __init__(self, filename=None):
super( FileInfo, self ).__init__()
self["name"] = filename
Observe o seguinte.
-
Podemos diretamente subclasse classes internas, como
dict
,list
,tuple
, etc. -
A função
super
alças rastreando superclasses desta classe e chamar funções em-los adequadamente.
Outras dicas
Em cada classe que você precisa para herdar, você pode executar um loop de cada classe que necessidades init'd após o início da classe criança ... um exemplo que pode copiado pode ser melhor compreendido ...
class Female_Grandparent:
def __init__(self):
self.grandma_name = 'Grandma'
class Male_Grandparent:
def __init__(self):
self.grandpa_name = 'Grandpa'
class Parent(Female_Grandparent, Male_Grandparent):
def __init__(self):
Female_Grandparent.__init__(self)
Male_Grandparent.__init__(self)
self.parent_name = 'Parent Class'
class Child(Parent):
def __init__(self):
Parent.__init__(self)
#---------------------------------------------------------------------------------------#
for cls in Parent.__bases__: # This block grabs the classes of the child
cls.__init__(self) # class (which is named 'Parent' in this case),
# and iterates through them, initiating each one.
# The result is that each parent, of each child,
# is automatically handled upon initiation of the
# dependent class. WOOT WOOT! :D
#---------------------------------------------------------------------------------------#
g = Female_Grandparent()
print g.grandma_name
p = Parent()
print p.grandma_name
child = Child()
print child.grandma_name
Você realmente não Have para chamar os métodos __init__
da classe base (ES), mas você geralmente deseja para fazê-lo, porque as classes de base vai fazer alguma initializations importantes lá que são necessários para o descanso dos métodos aulas para o trabalho.
Para outros métodos depende de suas intenções. Se você só quer acrescentar algo ao comportamento classes base que você vai querer chamar o método classes base também para o seu próprio código. Se você quiser mudar fundamentalmente o comportamento, você não pode chamar o método da classe base e implementar todas as funcionalidades diretamente na classe derivada.
Se a classe FileInfo tem mais de uma classe ancestral, então você definitivamente deve chamar todas as suas funções () __init __. Você também deve fazer o mesmo para o __ () função, __del que é um destruidor.
Sim, você deve chamar __init__
para cada classe pai. O mesmo vale para funções, se você está substituindo uma função que existe em ambos os pais.