24

I'm experimenting with OOP python and I wasn't sure about the __repr__ function inheritance. Since the parent class function looked like this:

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

I wanted to know if it is better to use a generic approach (which could be suitable for children classes as well) like the following one:

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

or if it is a good practice to override the function in every class.

Also, please ignore the encoding part, since I'm leaving it behind.

user2357112
  • 260,549
  • 28
  • 431
  • 505
dec0de_d00dle
  • 425
  • 1
  • 4
  • 13
  • 2
    Generally speaking, it's fine to override the method if you want don't want to extend it. – GIZ Jun 03 '17 at 08:51
  • If all the child classes have the `_param` attribute, then it's quite safe for them to inherit that `__repr__` from the parent class. – PM 2Ring Jun 03 '17 at 08:58

2 Answers2

18

Well the __repr__ has a special meaning in Pythons data model:

object.__repr__(self)

Called by the repr() built-in function to compute the “official” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value (given an appropriate environment). If this is not possible, a string of the form <...some useful description...> should be returned. The return value must be a string object. If a class defines __repr__() but not __str__(), then __repr__() is also used when an “informal” string representation of instances of that class is required.

This is typically used for debugging, so it is important that the representation is information-rich and unambiguous.

That means the string that is returned by __repr__ should be usable to create another object just like it. So __repr__ is something that quite often needs overriding, not because of the __class__.__name__ but because the "state" has to be captured in the representation.

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

Then you absolutely should override the __repr__ when you add parameters for __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))

But in case the __repr__ of the superclass still accurately "describes" the subclass then there's no point overloading the __repr__:

class B(A):
     pass

However it's always a good choice to use self.__class__.__name__ over hard-coding the class name, just in case you or someone else subclasses it.

Community
  • 1
  • 1
MSeifert
  • 145,886
  • 38
  • 333
  • 352
  • 3
    You should take the ability for recreating an object from its repr recomendtion with a grain of salt: it is great for some kindof objects, still it was thought up at a time when Pyhton's `input` would call "eval" on the value typed by the user: it was another mindset for interactive use of the Python language. Depending on the kind of object it is not really practical - and sometimes not even desirable - taht repr works this way. – jsbueno Jun 03 '17 at 10:04
  • 1
    @jsbueno It's more important for debugging (and when you post on StackOverflow). When the representation contains all necessary informations that define the instance then it's much easier to recreate a particular state or "see" what is going on. – MSeifert Jun 03 '17 at 13:34
  • I think `type(self).__name__` is a better choice for `__repr__` since it gives the *real* class name of `self`—that is what you want when you debug with `repr`—which might be different from its *virtual* class name, usually for proxy objects, such as those returned by `weakref.proxy` (cf. [my answer](https://stackoverflow.com/a/53757539/2326961)). – Géry Ogam Mar 31 '22 at 09:57
2

Yes - - it is not just "ok", but it is what is more practical in almost every project and class hierarchy.

Actually, this is almost a perfect "text book example" of when to use class inheritance, and just let the code in the superclasses be reused.

MSeifert
  • 145,886
  • 38
  • 333
  • 352
jsbueno
  • 99,910
  • 10
  • 151
  • 209