web-dev-qa-db-fra.com

Manière correcte d'écrire la fonction __repr__ avec héritage

J'expérimente avec OOP python et je n'étais pas sûr de la __repr__ héritage de fonction. Puisque la fonction de classe parent ressemblait à ceci:

def __repr__(self):
    '''Returns representation of the object'''
    return("{}({!r})".format("Class name", self._param))

Je voulais savoir s'il était préférable d'utiliser une approche générique (qui pourrait également convenir aux classes d'enfants) comme la suivante:

def __repr__(self):
    '''Returns representation of the object'''
    return("{}({!r})".format(self.__class__.__name__, self._param))

ou si c'est une bonne pratique de remplacer la fonction dans chaque classe.

Aussi, veuillez ignorer la partie encodage, car je la laisse derrière.

12
dec0de_d00dle

Eh bien, le __repr__ a une signification particulière dans le modèle de données Pythons:

object.__repr__(self)

Appelé par la fonction intégrée repr() pour calculer la représentation de chaîne "officielle" d'un objet. Si possible, cela devrait ressembler à une expression Python valide qui pourrait être utilisée pour recréer un objet avec la même valeur (dans un environnement approprié) . Si cela n'est pas possible, une chaîne de la forme <...some useful description...> Doit être renvoyée. La valeur de retour doit être un objet chaîne. Si une classe définit __repr__() mais pas __str__(), alors __repr__() est également utilisé lorsqu'une représentation sous forme de chaîne "informelle" des instances de cette classe est requise.

Ceci est généralement utilisé pour le débogage, il est donc important que la représentation soit riche en informations et sans ambiguïté.

Cela signifie que la chaîne renvoyée par __repr__ Devrait être utilisable pour créer un autre objet comme celui-ci. Donc __repr__ Est quelque chose qui assez souvent doit être remplacé, non pas à cause du __class__.__name__ Mais parce que "l'état" doit être capturé dans la représentation.

class A(object):
    def __init__(self, param):
        self._param = param

    def __repr__(self):
        '''Returns representation of the object'''
        return("{}({!r})".format(self.__class__.__name__, self._param))

Ensuite, vous devez absolument remplacer le __repr__ Lorsque vous ajoutez des paramètres pour __init__:

class B(A):
    def __init__(self, param1, param2):
        self._param = param1
        self._param2 = param2

    def __repr__(self):
        '''Returns representation of the object'''
        return("{}({!r})".format(self.__class__.__name__, self._param, self._param2))

Mais dans le cas où le __repr__ De la superclasse précise "décrit" la sous-classe, il n'y a aucun intérêt à surcharger le __repr__ :

class B(A):
     pass

Cependant, c'est toujours un bon choix d'utiliser self.__class__.__name__ Plutôt que de coder en dur le nom de la classe, juste au cas où vous ou quelqu'un d'autre le sous-classeriez.

9
MSeifert

Oui - - ce n'est pas seulement "ok", mais c'est ce qui est plus pratique dans presque chaque projet et hiérarchie de classe.

En fait, c'est presque un "exemple de livre de texte" parfait pour savoir quand utiliser l'héritage de classe, et juste laisser le code dans les superclasses être réutilisé.

1
jsbueno