# 7.3. Operator Increment

• x += y - will call method "iadd" on object x (x.__iadd__(y))

• x -= y - will call method "isub" on object x (x.__isub__(y))

• x *= y - will call method "imul" on object x (x.__imul__(y))

• x **= y - will call method "ipow" on object x (x.__ipow__(y))

• x @= y - will call method "imatmul" on object x (x.__imatmul__(y))

• x /= y - will call method "itruediv" on object x (x.__itruediv__(y))

• x //= y - will call method "ifloordiv" on object x (x.__ifloordiv__(y))

• x %= y - will call method "imod" on object x (x.__imod__(y))

Operator

Method

obj += other

obj.__iadd__(other)

obj -= other

obj.__isub__(other)

obj *= other

obj.__imul__(other)

obj **= other

obj.__ipow__(other)

obj @= other

obj.__imatmul__(other)

obj /= other

obj.__itruediv__(other)

obj //= other

obj.__ifloordiv__(other)

obj %= other

obj.__imod__(other)

## 7.3.1. SetUp

>>> from dataclasses import dataclass


## 7.3.2. Problem

>>> @dataclass
... class Vector:
...     x: int
...     y: int
...
...         return Vector(x=self.x + other.x,
...                       y=self.y + other.y)


Let's define two vectors:

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

>>> print(a)
Vector(x=1, y=2)


Show memory address of a a object:

>>> hex(id(a))
'0x1054c7fe0'


>>> a += b


We can see, that the object a is not the same:

>>> hex(id(a))
'0x1054fc530'


We can inspect the result, the calculations are correct:

>>> print(a)
Vector(x=3, y=6)


## 7.3.3. Solution

>>> @dataclass
... class Vector:
...     x: int
...     y: int
...
...         self.x += other.x
...         self.y += other.y
...         return self


Let's define two vectors:

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

>>> print(a)
Vector(x=1, y=2)


Show memory address of a a object:

>>> hex(id(a))
'0x1054fc410'


>>> a += b


We can see, that the object a is the same, but it is changed:

>>> hex(id(a))
'0x1054fc410'


We can inspect the result, the calculations are correct:

>>> print(a)
Vector(x=3, y=6)


## 7.3.4. Syntax

>>> @dataclass
... class Vector:
...     x: int
...     y: int
...
...     def __isub__(self, other): ...              # x -= y    calls x.__isub__(y)
...     def __imul__(self, other): ...              # x *= y    calls x.__imul__(y)
...     def __ipow__(self, power, modulo=None): ... # x **= y   calls x.__ipow__(y)
...     def __imatmul__(self, other): ...           # x @= y    calls x.__imatmul__(y)
...     def __itruediv__(self, other): ...          # x /= y    calls x.__itruediv__(y)
...     def __ifloordiv__(self, other): ...         # x //= y   calls x.__ifloordiv__(y)
...     def __imod__(self, other): ...              # x %= y    calls x.__imod__(y)


## 7.3.5. Example

>>> @dataclass
... class Vector:
...     x: int
...     y: int
...
...         self.x += other.x
...         self.y += other.y
...         return self
...
>>>
>>>
>>> a = Vector(x=1, y=2)
>>>
>>> a += Vector(x=10, y=20)
>>> print(a)
Vector(x=11, y=22)


>>> @dataclass
... class Vector:
...     x: int
...     y: int
...
...         return Vector(
...             x = self.x + other.x,
...             y = self.y + other.y)
>>>
>>>
>>> a = Vector(x=1, y=2)
>>>
>>> id(a)
4435911632
>>>
>>> a += Vector(x=10, y=20)
>>> id(a)
4435972432
>>>
>>> print(a)
Vector(x=11, y=22)

>>> @dataclass
... class Vector:
...     x: int
...     y: int
...
...         self.x += other.x
...         self.y += other.y
...         return self
>>>
>>>
>>> a = Vector(x=1, y=2)
>>>
>>> id(a)
4437201808
>>>
>>> a += Vector(x=10, y=20)
>>> id(a)
4437201808
>>>
>>> print(a)
Vector(x=11, y=22)


## 7.3.7. Use Case - 0x01

>>> hero['gold'] += dragon['gold']


## 7.3.8. Use Case - 0x02

>>> class Group:
...     def __init__(self):
...         self.members = []
...
...         self.members.append(other)
...         return self
>>>
>>>
>>>
['mwatney', 'mlewis', 'rmartinez']


## 7.3.9. Assignments

"""
* Complexity: easy
* Lines of code: 3 lines
* Time: 3 min

English:
1. Overload operator +=
2. Make User objects able to add Groups, for example:
a. mark = User(firstname='Mark', lastname='Watney')
b. mark += Group(1, 'admins')
c. 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:
a. mark = User(firstname='Mark', lastname='Watney')
b. mark += Group(1, 'admins')
c. mark += Group(2, 'staff')
3. Uruchom doctesty - wszystkie muszą się powieść

Hints:
* object.__iadd__() -> self

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

>>> mark = User(firstname='Mark', lastname='Watney', groups=[])
>>> mark += Group(2, 'staff')

>>> pprint(mark, width=50)
User(firstname='Mark',
lastname='Watney',
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:
# a. mark = User(firstname='Mark', lastname='Watney')
# b. mark += Group(1, 'admins')
# c. mark += Group(2, 'staff')
# type: type[User]
@dataclass
class User:
firstname: str
lastname: str
groups: list[Group]