8.2. Operator Left

  • a + b - will call method "add" on object a (a.__add__(b))

  • a - b - will call method "sub" on object a (a.__sub__(b))

  • a * b - will call method "mul" on object a (a.__mul__(b))

  • a ** b - will call method "pow" on object a (a.__pow__(b))

  • a @ b - will call method "matmul" on object a (a.__matmul__(b))

  • a / b - will call method "truediv" on object a (a.__truediv__(b))

  • a // b - will call method "floordiv" on object a (a.__floordiv__(b))

  • a % b - will call method "mod" on object a (a.__mod__(b))

Table 8.1. Numerical Operator Overload

Operator

Method

obj + other

obj.__add__(other)

obj - other

obj.__sub__(other)

obj * other

obj.__mul__(other)

obj ** other

obj.__pow__(other)

obj @ other

obj.__matmul__(other)

obj / other

obj.__truediv__(other)

obj // other

obj.__floordiv__(other)

obj % other

obj.__mod__(other)

8.2.1. SetUp

>>> from dataclasses import dataclass

8.2.2. Syntax

>>> class MyClass:
...     def __add__(self, other): ...               # a + b
...     def __sub__(self, other): ...               # a - b
...     def __mul__(self, other): ...               # a * b
...     def __pow__(self, power, modulo=None): ...  # a ** b
...     def __matmul__(self, other): ...            # a @ b
...     def __truediv__(self, other): ...           # a / b
...     def __floordiv__(self, other): ...          # a // b
...     def __mod__(self, other): ...               # a % b

8.2.3. 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)
>>> c = Vector(x=5, y=6)
>>> (a+b) - c
Traceback (most recent call last):
TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'

8.2.4. 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 __add__(self, other):
...         new_x = self.x + other.x
...         new_y = self.y + other.y
...         return Vector(new_x, new_y)
...
...     def __sub__(self, other):
...         new_x = self.x - other.x
...         new_y = self.y - other.y
...         return Vector(new_x, new_y)
>>>
>>>
>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>> c = Vector(x=5, y=6)
>>> (a+b) - c
Vector(x=-1, y=0)

8.2.5. Operator

  • operator.add(a, b) - add - a + b

  • operator.sub(a, b) - sub - a - b

  • operator.mul(a, b) - mul - a * b

  • operator.pow(a, b) - pow - a ** b

  • operator.matmul(a, b) - matmul - a @ b

  • operator.truediv(a, b) - truediv - a / b

  • operator.floordiv(a, b) - floordiv - a // b

  • operator.mod(a, b) - mod - a % b

>>> import operator
>>> operator.add(1, 2)
3
>>> operator.sub(1, 2)
-1
>>> operator.mul(1, 2)
2
>>> operator.pow(2, 3)
8
>>> operator.matmul(1, 2)
Traceback (most recent call last):
TypeError: unsupported operand type(s) for @: 'int' and 'int'
>>> operator.truediv(1, 2)
0.5
>>> operator.floordiv(1, 2)
0
>>> operator.mod(1, 2)
1

8.2.6. Use Case - 1

>>> @dataclass
... class Point:
...     x: int
...     y: int
>>>
>>> @dataclass
... class Hero:
...     name: str
...     position_x: int = 0
...     position_y: int = 0
...
...     def __matmul__(self, point):
...         self.position_x = point.x
...         self.position_y = point.y
>>>
>>>
>>> hero = Hero('Twardowski')
>>> hero.position_x, hero.position_y
(0, 0)
>>>
>>> hero @ Point(x=50, y=120)
>>>
>>> hero.position_x, hero.position_y
(50, 120)

8.2.7. Use Case - 2

>>> class User:
...     def __init__(self, firstname, lastname):
...         self.firstname = firstname
...         self.lastname = lastname
...
...     def __matmul__(self, domain):
...         username = f'{self.firstname}.{self.lastname}'.lower()
...         return f'{username}@{domain}'
>>>
>>>
>>> mark = User('Mark', 'Watney')
>>>
>>> mark @ 'nasa.gov'
'mark.watney@nasa.gov'
>>>
>>> mark @ 'esa.int'
'mark.watney@esa.int'

8.2.8. Use Case - 3

>>> import sys
>>>
>>>
>>> class Path:
...     def __init__(self, path=None):
...         if path is None:
...             if sys.platform == 'windows':
...                 self.path = 'c:'
...             else:
...                 self.path = ''
...         else:
...             self.path = path
...
...     def __str__(self):
...         return f'{self.path}'
...
...     def __truediv__(self, other):
...         if sys.platform == 'windows':
...             return Path(rf'{self.path}\{other}')
...         else:
...             return Path(f'{self.path}/{other}')
>>>
>>>
>>> path = Path() / 'Users' / 'mwatney' / 'myfile.txt'

On macOS and Linux:

>>> print(path)
/Users/mwatney/myfile.txt

On Windows:

>>> print(path)  
c:\Users\mwatney\myfile.txt

8.2.9. 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 Left Add
# - Difficulty: easy
# - Lines: 3
# - Minutes: 3

# %% English
# 1. Modify class `Vector`
# 2. Overload `+` operator to implement an addition of two vectors
# 3. Formula: `A+B = (Ax+Bx, Ay+By)`
# 4. Run doctests - all must succeed

# %% Polish
# 1. Zmodyfikuj klasę `Vector`
# 2. Przeciąż operator `+` aby zaimplementować dodawanie dwóch wektorów
# 3. Wzór: `A+B = (Ax+Bx, Ay+By)`
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `object.__add__()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> assert hasattr(Vector, '__add__'), \
'Class `Vector` has no `__add__` method'
>>> assert callable(Vector.__add__), \
'Class `Vector` has `__add__` attribute, which is not callable'

>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>> result = a + b

>>> print(result)
Vector(x=4, y=6)
"""

from dataclasses import dataclass


@dataclass
class Vector:
    x: int
    y: int

# Modify class `Vector`
# Overload `+` operator to implement an addition of two vectors
# Formula: `A+B = (Ax+Bx, Ay+By)`
# type: Callable[[Vector, Vector], Vector]
...

# %% 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 Left Sub
# - Difficulty: easy
# - Lines: 3
# - Minutes: 3

# %% English
# 1. Modify class `Vector`
# 2. Overload `-` operator to implement a subtraction of two vectors
# 3. Formula: `A-B = (Ax-Bx, Ay-By)`
# 4. Run doctests - all must succeed

# %% Polish
# 1. Zmodyfikuj klasę `Vector`
# 2. Przeciąż operator `-` aby zaimplementować odejmowanie dwóch wektorów
# 3. Wzór: `A-B = (Ax-Bx, Ay-By)`
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `object.__sub__()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> assert hasattr(Vector, '__sub__'), \
'Class `Vector` has no `__sub__` method'
>>> assert callable(Vector.__sub__), \
'Class `Vector` has `__sub__` attribute, which is not callable'

>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>> result = a - b

>>> print(result)
Vector(x=-2, y=-2)
"""

from dataclasses import dataclass


@dataclass
class Vector:
    x: int
    y: int

# Modify class `Vector`
# Overload `-` operator to implement a subtraction of two vectors
# Formula: `A-B = (Ax-Bx, Ay-By)`
# type: Callable[[Vector, Vector], Vector]
...

# %% 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 Left Sub
# - Difficulty: easy
# - Lines: 3
# - Minutes: 3

# %% English
# 1. Modify class `Vector`
# 2. Overload `@` operator to implement a scalar multiplication of vectors
# 3. Formula: `A@B = (A1*B1, A2*B2)`
# 4. Run doctests - all must succeed

# %% Polish
# 1. Zmodyfikuj klasę `Vector`
# 2. Przeciąż operator `@` aby zaimplementować mnożenie skalarne wektorów
# 3. Wzór: `A@B = (A1*B1, A2*B2)`
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `object.__matmul__()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> assert hasattr(Vector, '__matmul__'), \
'Class `Vector` has no `__matmul__` method'
>>> assert callable(Vector.__matmul__), \
'Class `Vector` has `__matmul__` attribute, which is not callable'

>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>> result = a @ b

>>> print(result)
Vector(x=3, y=8)
"""

from dataclasses import dataclass


@dataclass
class Vector:
    x: int
    y: int

# Modify class `Vector`
# Overload `@` operator to implement scalar multiplication of vectors
# Formula: `A@B = (A1*B1, A2*B2)`
# type: Callable[[Vector, Vector], Vector]
...

# %% 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 Left Sub
# - Difficulty: easy
# - Lines: 3
# - Minutes: 3

# %% English
# 1. Modify class `Vector`
# 2. Overload `*` operator to implement an element-wise product of vectors
# 3. Formula: `A*B = (Ax*Bx) + (Ay*By)`
# 4. Run doctests - all must succeed

# %% Polish
# 1. Zmodyfikuj klasę `Vector`
# 2. Przeciąż operator `*` aby zaimplementować mnożenie wektorowe wektorów
# 3. Wzór: `A*B = (Ax*Bx) + (Ay*By)`
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `object.__mul__()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> assert hasattr(Vector, '__mul__'), \
'Class `Vector` has no `__mul__` method'
>>> assert callable(Vector.__mul__), \
'Class `Vector` has `__mul__` attribute, which is not callable'

>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>> result = a * b

>>> print(result)
11
"""

from dataclasses import dataclass


@dataclass
class Vector:
    x: int
    y: int

# Modify class `Vector`
# Overload `*` operator to implement an element-wise product of vectors
# Formula: `A*B = (Ax*Bx) + (Ay*By)`
# type: Callable[[Vector, Vector], int|float]
...