8.3. Operator Increment
x += y
- will call method "iadd" on objectx
(x.__iadd__(y)
)x -= y
- will call method "isub" on objectx
(x.__isub__(y)
)x *= y
- will call method "imul" on objectx
(x.__imul__(y)
)x **= y
- will call method "ipow" on objectx
(x.__ipow__(y)
)x @= y
- will call method "imatmul" on objectx
(x.__imatmul__(y)
)x /= y
- will call method "itruediv" on objectx
(x.__itruediv__(y)
)x //= y
- will call method "ifloordiv" on objectx
(x.__ifloordiv__(y)
)x %= y
- will call method "imod" on objectx
(x.__imod__(y)
)
Operator |
Method |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8.3.1. Syntax
>>> class MyClass:
... def __iadd__(self, other): ... # a += b
... def __isub__(self, other): ... # a -= b
... def __imul__(self, other): ... # a *= b
... def __ipow__(self, power, modulo=None): ... # a **= b
... def __imatmul__(self, other): ... # a @= b
... def __itruediv__(self, other): ... # a /= b
... def __ifloordiv__(self, other): ... # a //= b
... def __imod__(self, other): ... # a %= b
8.3.2. Problem
>>> class Vector:
... x: int
... y: int
...
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
... def __repr__(self):
... return f'Vector(x={self.x}, y={self.y})'
>>>
>>>
>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>>
>>> a += b
Traceback (most recent call last):
TypeError: unsupported operand type(s) for +=: 'Vector' and 'Vector'
8.3.3. Solution
>>> class Vector:
... x: int
... y: int
...
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
... def __repr__(self):
... return f'Vector(x={self.x}, y={self.y})'
...
... def __iadd__(self, other):
... self.x += other.x
... self.y += other.y
... return self
>>>
>>>
>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>> a += b
>>>
>>> print(a)
Vector(x=4, y=6)
8.3.4. Add vs. Iadd
>>> class Vector:
... x: int
... y: int
...
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
... def __repr__(self):
... return f'Vector(x={self.x}, y={self.y})'
...
... def __add__(self, other):
... return Vector(x=self.x + other.x,
... y=self.y + other.y)
>>>
>>>
>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>>
>>> id(a)
4387892080
>>>
>>> a += b
>>>
>>> id(a)
4387901360
>>>
>>> print(a)
Vector(x=4, y=6)
>>> class Vector:
... x: int
... y: int
...
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
... def __repr__(self):
... return f'Vector(x={self.x}, y={self.y})'
...
... def __iadd__(self, other):
... self.x += other.x
... self.y += other.y
... return self
>>>
>>>
>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>>
>>> id(a)
4387904192
>>>
>>> a += b
>>>
>>> id(a)
4387904192
>>>
>>> print(a)
Vector(x=4, y=6)
8.3.5. Returning Self
Always return
self
from increment methodsPython will assign to the left-hand side variable the result of the increment method
>>> class Vector:
... x: int
... y: int
...
... def __init__(self, x, y):
... self.x = x
... self.y = y
...
... def __repr__(self):
... return f'Vector(x={self.x}, y={self.y})'
...
... def __iadd__(self, other):
... self.x += other.x
... self.y += other.y
>>>
>>>
>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>>
>>> a += b
>>>
>>> print(a)
None
>>>
>>> a is None
True
8.3.6. Use Case - 1
>>> hero['gold'] += dragon['gold']
8.3.7. Use Case - 2
>>> class Group:
... def __init__(self):
... self.members = []
...
... def __iadd__(self, other):
... self.members.append(other)
... return self
>>>
>>>
>>> admins = Group()
>>> admins += 'mwatney'
>>> admins += 'mlewis'
>>> admins += 'rmartinez'
>>>
>>> admins.members
['mwatney', 'mlewis', 'rmartinez']
8.3.8. 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 Increment Add
# - Difficulty: easy
# - Lines: 3
# - Minutes: 3
# %% English
# 1. Overload operator `+=`
# 2. Make `User` objects able to add `Groups`, for example:
# - `mark = User(firstname='Mark', lastname='Watney')`
# - `mark += Group(1, 'admins')`
# - `mark += Group(2, 'staff')`
# 3. Run doctests - all must succeed
# %% Polish
# 1. Przeciąż operator `+=`
# 2. Spraw aby do obiektów klasy `User` można dodać `Group`, przykład:
# - `mark = User(firstname='Mark', lastname='Watney')`
# - `mark += Group(1, 'admins')`
# - `mark += Group(2, 'staff')`
# 3. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `object.__iadd__() -> self`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> from pprint import pprint
>>> mark = User(firstname='Mark', lastname='Watney', groups=[])
>>> mark += Group(1, 'admins')
>>> mark += Group(2, 'staff')
>>> pprint(mark, width=50)
User(firstname='Mark',
lastname='Watney',
groups=[Group(gid=1, name='admins'),
Group(gid=2, name='staff')])
"""
from dataclasses import dataclass
@dataclass
class Group:
gid: int
name: str
# Make `User` objects able to add `Groups`, for example:
# - `mark = User(firstname='Mark', lastname='Watney')`
# - `mark += Group(1, 'admins')`
# - `mark += Group(2, 'staff')`
# type: type[User]
@dataclass
class User:
firstname: str
lastname: str
groups: list[Group]