19.2. OOP Repr
Typing
obj
into REPL (console) callsrepr(obj)
Calling
repr(obj)
callsobj.__repr__()
Method
obj.__repr__()
must returnstr
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
19.2.1. Default
Object without __repr__()
method overloaded prints their memory address:
>>> class User:
... def __init__(self, firstname, lastname):
... self.firstname = firstname
... self.lastname = lastname
>>>
>>>
>>> mark = User('Mark', 'Watney')
>>>
>>> mark
<__main__.User object at 0x...>
>>>
>>> repr(mark)
'<__main__.User object at 0x...>'
>>>
>>> mark.__repr__()
'<__main__.User object at 0x...>'
19.2.2. Overloaded
>>> class User:
... 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=})'
>>>
>>>
>>> mark = User('Mark', 'Watney')
>>>
>>> mark
User(firstname='Mark', lastname='Watney')
>>>
>>> repr(mark)
"User(firstname='Mark', lastname='Watney')"
>>>
>>> mark.__repr__()
"User(firstname='Mark', lastname='Watney')"
19.2.3. Nested
Printing
list
will call__repr__()
method on each element
>>> data = [1,2,3]
>>> print(data)
[1, 2, 3]
>>> class MyClass:
... def __repr__(self): return 'repr'
... def __str__(self): return 'str'
>>>
>>> data = [
... MyClass(),
... MyClass(),
... MyClass(),
... ]
>>>
>>>
>>> print(data)
[repr, repr, repr]
>>>
>>> data
[repr, repr, repr]
>>>
>>> str(data)
'[repr, repr, repr]'
>>>
>>> repr(data)
'[repr, repr, repr]'
19.2.4. Use Case - 1
Printing list
will call __repr__()
method on each element:
>>> class User:
... def __init__(self, firstname, lastname):
... self.firstname = firstname
... self.lastname = lastname
...
... def __repr__(self):
... return f'{self.firstname} {self.lastname}'
>>>
>>> admins = [
... User('Mark', 'Watney'),
... User('Melissa', 'Lewis'),
... User('Rick', 'Martinez'),
... ]
>>>
>>> print(admins)
[Mark Watney, Melissa Lewis, Rick Martinez]
19.2.5. Case Study
SECOND = 1
MINUTE = 60 * SECOND
HOUR = 60 * MINUTE
DAY = 24 * HOUR
WEEK = 7 * DAY
YEAR = 365.25 * DAY
MONTH = YEAR / 12
SOL = 24*HOUR + 39*MINUTE + 35.244*SECOND
class Mission:
def __init__(self, name, duration):
self.name = name
self.duration = duration
def __str__(self):
return f'{self.name}'
def __format__(self, unit):
duration = self.duration
match unit:
case 's' | 'sec' | 'seconds': duration /= SECOND
case 'm' | 'min' | 'minutes': duration /= MINUTE
case 'h' | 'hour' | 'hours': duration /= HOUR
case 'd' | 'day' | 'days': duration /= DAY
case 'w' | 'week' | 'weeks': duration /= WEEK
case 'mth'| 'month' | 'months': duration /= MONTH
case 'y' | 'year' | 'years': duration /= YEAR
case 'sol': duration /= SOL
return f'{duration:.1f} {unit}'
ares3 = Mission('Ares3', duration=543*SOL)
print(f'Mission Ares 3 duration was: {ares3:months}')
# Mission Ares 3 duration was: 18.3 months
19.2.6. Assignments
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Operator String Repr
# - Difficulty: easy
# - Lines: 3
# - Minutes: 2
# %% English
# 1. Modify `User` to overwrite `__repr__()` method
# 2. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj klasę `User` aby nadpisać metodę `__repr__()`
# 2. Uruchom doctesty - wszystkie muszą się powieść
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> mark = User('Mark', 'Watney')
>>> mark
User(firstname='Mark', lastname='Watney')
"""
# Modify `User` to overwrite `__repr__()` method
class User:
def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Operator String Repr
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2
# %% English
# 1. Modify `User` to overwrite `__repr__()` method
# 2. Method should return proper class name on inheritance
# 3. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj klasę `User` aby nadpisać metodę `__repr__()`
# 2. Metoda powinna zwracać odpowiednią nazwę klasy przy dziedziczeniu
# 3. Uruchom doctesty - wszystkie muszą się powieść
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> mark = User('Mark', 'Watney')
>>> mark
User(firstname='Mark', lastname='Watney')
>>> melissa = Admin('Melissa', 'Lewis')
>>> melissa
Admin(firstname='Melissa', lastname='Lewis')
"""
# Modify `User` to overwrite `__repr__()` method
# Method should return proper class name on inheritance
class User:
def __init__(self, firstname, lastname):
self.firstname = firstname
self.lastname = lastname
def __repr__(self):
firstname = self.firstname
lastname = self.lastname
return f'User({firstname=}, {lastname=})'
class Admin(User):
pass
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Operator String Repr
# - Difficulty: easy
# - Lines: 3
# - Minutes: 3
# %% English
# 1. Modify `Iris` to overwrite `__repr__()` method
# 2. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj klasę `Iris` aby nadpisać metodę `__repr__()`
# 2. Uruchom doctesty - wszystkie muszą się powieść
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> from inspect import isclass, ismethod
>>> assert isclass(Iris)
>>> iris = Iris(DATA)
>>> assert hasattr(Iris, '__repr__')
>>> assert ismethod(iris.__repr__)
>>> repr(iris)
"Iris(values=[4.7, 3.2, 1.3, 0.2], species='setosa')"
"""
DATA = (4.7, 3.2, 1.3, 0.2, 'setosa')
# Modify `Iris` to overwrite `__repr__()` method
# repr() -> Iris(values=[4.7, 3.2, 1.3, 0.2], species='setosa')
class Iris:
values: list
species: str
def __init__(self, data):
self.values = list(data[:-1])
self.species = str(data[-1])
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Operator String Nested
# - Difficulty: medium
# - Lines: 9
# - Minutes: 8
# %% English
# 1. Modify classes to overwrite `__str__()` and `__repr__()` methods
# 2. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj klasy aby nadpisać metody `__str__()` and `__repr__()`
# 2. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - Define `Accounts.__str__()`
# - Define `User.__str__()`
# - Define `Group.__repr__()`
# - Printing list will call repr on all elements
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> result = User('Mark', 'Watney')
>>> print(result)
Mark Watney
>>> result = User('Melissa', 'Lewis')
>>> print(result)
Melissa Lewis
>>> result = User('Rick', 'Martinez')
>>> print(result)
Rick Martinez
>>> Group(gid=1, name='admins')
1(admins)
>>> Group(gid=2, name='staff')
2(staff)
>>> Group(gid=3, name='users')
3(users)
>>> result = Accounts(users=[])
>>> print(result)
<BLANKLINE>
>>> result = User('Mark', 'Watney', groups=[
... Group(gid=2, name='staff'),
... ])
>>> print(result)
Mark Watney member of [2(staff)]
>>> result = User('Melissa', 'Lewis', groups=[
... Group(gid=1, name='admins'),
... Group(gid=2, name='staff'),
... ])
>>> print(result)
Melissa Lewis member of [1(admins), 2(staff)]
>>> result = Accounts([
... User('Mark', 'Watney', groups=[
... Group(gid=2, name='staff'),
... ]),
... User('Melissa', 'Lewis', groups=[
... Group(gid=1, name='admins'),
... Group(gid=2, name='staff'),
... ]),
... User('Rick', 'Martinez'),
... ])
>>>
>>> print(result) # doctest: +NORMALIZE_WHITESPACE
Mark Watney member of [2(staff)]
Melissa Lewis member of [1(admins), 2(staff)]
Rick Martinez
"""
class Accounts:
def __init__(self, users):
self.users = users
class User:
def __init__(self, firstname, lastname, groups=None):
self.firstname = firstname
self.lastname = lastname
self.groups = groups if groups else []
class Group:
def __init__(self, gid, name):
self.gid = gid
self.name = name