J'ai une classe de base avec beaucoup d'arguments __init__
:
def BaseClass(object):
def __init__(self, a, b, c, d, e, f, ...):
self._a=a+b
self._b=b if b else a
...
Toutes les classes héritées doivent exécuter la méthode __init__
De la classe de base.
Je peux écrire une méthode __init__()
dans chacune des classes héritées qui appellerait la superclasse __init__
, Mais ce serait une sérieuse duplication de code:
def A(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
def B(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
def C(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
super(A, self).__init__(a, b, c, d, e, f, ...)
...
Quelle est la façon la plus pythonique d'appeler automatiquement la superclasse __init__
?
super(SubClass, self).__init__(...)
Pensez à utiliser * args et ** kw si cela aide à résoudre votre cauchemar variable.
Vous devez l'écrire explicitement, mais d'un autre côté, si vous avez beaucoup d'arguments, vous devriez probablement utiliser * args pour les arguments positionnels et ** kwargs pour les arguments du mot clé.
class SubClass(BaseClass):
def __init__(self, *args, **kwargs):
super(SubClass, self).__init__(*args, **kwargs)
# SubClass initialization code
Une autre technique que vous pouvez utiliser consiste à réduire le code dans init puis à la fin de la fonction init, appelez une autre fonction personnalisée. Ensuite, dans la sous-classe, il vous suffit de remplacer la fonction personnalisée
class BaseClass(object):
def __init__(self, *args, **kwargs):
# initialization code
self._a = kwargs.get('a')
...
# custom code for subclass to override
self.load()
def load():
pass
class SubClass(BaseClass)
def load():
# SubClass initialization code
...
Si les classes dérivées n'implémentent rien au-delà de ce que fait déjà la classe de base __init__()
, omettez simplement les méthodes des classes dérivées __init__()
- la classe de base __init__()
est alors appelé automatiquement.
Si, OTOH, vos classes dérivées ajoutent du travail supplémentaire dans leur __init__()
, et que vous ne voulez pas qu'elles appellent explicitement leur classe de base __init__()
, vous pouvez le faire:
class BaseClass(object):
def __new__(cls, a, b, c, d, e, f, ...):
new = object.__new__(cls)
new._a=a+b
new._b=b if b else a
...
return new
class A(BaseClass):
''' no __init__() at all here '''
class B(BaseClass):
def __init__(self, a, b, c, d, e, f, ...):
''' do stuff with init params specific to B objects '''
Puisque __new__()
est toujours appelé automatiquement, aucun travail supplémentaire n'est requis dans les classes dérivées.
À moins que vous ne fassiez quelque chose d'utile dans les méthodes de la sous-classe __init__()
, vous n'avez pas à la remplacer.
def BaseClass(object):
def __init__(self, a, b, c, d, e, f, ...):
self._a=a+b
self._b=b if b else a
...
def A(BaseClass):
def some_other_method(self):
pass
def B(BaseClass):
pass
Peut-être qu'une implémentation plus claire pour votre cas utilise ** kwargs combinée avec de nouveaux arguments ajoutés dans votre classe dérivée comme dans:
class Parent:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
class Child(Parent):
def __init__(self, d, **kwargs):
super(Child, self).__init__(**kwargs)
self.d = d
Par cette méthode, vous évitez la duplication de code mais conservez l'ajout implicite d'arguments dans votre classe dérivée.
Dans la version 2.6 et inférieure pour hériter init de la classe de base, il n'y a pas de super fonction, vous pouvez hériter de la manière suivante:
class NewClass():
def __init__():
BaseClass.__init__(self, *args)
Ajout d'une implémentation Pythonic. En supposant que vous souhaitez que tous les attributs soient transmis, vous pouvez utiliser le code ci-dessous. (Peut également conserver/supprimer des clés kwargs spécifiques si vous voulez un sous-ensemble).
def A(BaseClass):
def __init__(self, *args, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
base = BaseClass(...)
new = A( **base.__dict__ )