6.3. Operator String Repr

  • Typing obj into REPL (console) calls repr(obj)

  • Calling repr(obj) calls obj.__repr__()

  • Method obj.__repr__() must return str

  • Intended for developers of your class

  • Shows object representation

  • Copy-paste for creating object with the same values

  • Useful for debugging

  • Printing list will call __repr__() method on each element

6.3.1. Inherited

Object without __repr__() method overloaded prints their memory address:

>>> class Astronaut:
...     def __init__(self, firstname, lastname):
...         self.firstname = firstname
...         self.lastname = lastname
>>>
>>>
>>> astro = Astronaut('Mark', 'Watney')
>>>
>>> astro  
<__main__.Astronaut object at 0x...>
>>>
>>> repr(astro)  
'<__main__.Astronaut object at 0x...>'
>>>
>>> astro.__repr__()  
'<__main__.Astronaut object at 0x...>'

6.3.2. Overloaded

>>> class Astronaut:
...     def __init__(self, firstname, lastname):
...         self.firstname = firstname
...         self.lastname = lastname
...
...     def __repr__(self):
...         clsname = self.__class__.__name__
...         firstname = self.firstname
...         lastname = self.lastname
...         return f'{clsname}({firstname=}, {lastname=})'
>>>
>>>
>>> astro = Astronaut('Mark', 'Watney')
>>>
>>> astro
Astronaut(firstname='Mark', lastname='Watney')
>>>
>>> repr(astro)
"Astronaut(firstname='Mark', lastname='Watney')"
>>>
>>> astro.__repr__()
"Astronaut(firstname='Mark', lastname='Watney')"

6.3.3. Nested

  • Printing list will call __repr__() method on each element

>>> data = [1,2,3]
>>> print(data)
[1, 2, 3]

Printing list will call __repr__() method on each element:

>>> class Astronaut:
...     def __init__(self, name):
...         self.name = name
>>>
>>>
>>> crew = [Astronaut('Mark Watney'),
...         Astronaut('Melissa Lewis'),
...         Astronaut('Rick Martinez')]
>>>
>>> print(crew)  
[<__main__.Astronaut object at 0x...>, <__main__.Astronaut object at 0x...>, <__main__.Astronaut object at 0x...>]
>>> class Astronaut:
...     def __init__(self, name):
...         self.name = name
...
...     def __repr__(self):
...         return f'{self.name}'
>>>
>>> crew = [Astronaut('Mark Watney'),
...         Astronaut('Melissa Lewis'),
...         Astronaut('Rick Martinez')]
>>>
>>> print(crew)
[Mark Watney, Melissa Lewis, Rick Martinez]

6.3.4. Assignments

Code 6.48. Solution
"""
* Assignment: Operator String Repr
* Required: yes
* Complexity: easy
* Lines of code: 3 lines
* Time: 5 min

English:
    1. Overload `repr()`
    2. Run doctests - all must succeed

Polish:
    1. Przeciąż `repr()`
    2. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from inspect import isclass, ismethod

    >>> assert isclass(Iris)
        >>> iris = Iris(DATA)

    >>> assert hasattr(Iris, '__repr__')
    >>> assert ismethod(iris.__repr__)
    >>> repr(iris)
    "Iris(features=[4.7, 3.2, 1.3, 0.2], label='setosa')"
"""

DATA = (4.7, 3.2, 1.3, 0.2, 'setosa')

# repr() -> Iris(features=[4.7, 3.2, 1.3, 0.2], label='setosa')
class Iris:
    features: list
    label: str

    def __init__(self, data):
        self.features = list(data[:-1])
        self.label = str(data[-1])


Code 6.49. Solution
"""
* Assignment: Operator String Nested
* Required: yes
* Complexity: medium
* Lines of code: 9 lines
* Time: 13 min

English:
    1. Overload `str` and `repr` to achieve desired printing output
    2. Run doctests - all must succeed

Polish:
    1. Przeciąż `str` i `repr` aby osiągnąć oczekiwany rezultat wypisywania
    2. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * Define `Crew.__str__()`
    * Define `Astronaut.__str__()` and `Astronaut.__repr__()`
    * Define `Mission.__repr__()`

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> melissa = Astronaut('Melissa Lewis')
    >>> print(f'Commander: \\n{melissa}\\n')  # doctest: +NORMALIZE_WHITESPACE
    Commander:
    Melissa Lewis

    >>> mark = Astronaut('Mark Watney', missions=[
    ...     Mission(2035, 'Ares 3')])
    >>> print(f'Space Pirate: \\n{mark}\\n')  # doctest: +NORMALIZE_WHITESPACE
    Space Pirate:
    Mark Watney veteran of [
          2035: Ares 3]

    >>> crew = Crew([
    ...     Astronaut('Pan Twardowski', missions=[
    ...         Mission(1969, 'Apollo 11'),
    ...         Mission(2024, 'Artemis 3'),
    ...     ]),
    ...     Astronaut('José Jiménez'),
    ...     Astronaut('Mark Watney', missions=[
    ...         Mission(2035, 'Ares 3'),
    ...     ]),
    ... ])

    >>> print(f'Crew: \\n{crew}')  # doctest: +NORMALIZE_WHITESPACE
    Crew:
    Pan Twardowski veteran of [
          1969: Apollo 11,
          2024: Artemis 3]
    José Jiménez
    Mark Watney veteran of [
          2035: Ares 3]
"""


class Crew:
    def __init__(self, members):
        self.members = members


class Astronaut:
    def __init__(self, name, missions=None):
        self.name = name
        self.missions = missions if missions else []


class Mission:
    def __init__(self, year, name):
        self.year = year
        self.name = name