Functions
def __add__(self, value: int, /) -> int: ...
π __add__
This is the special magic method that implements the + operator.
If a class defines __add__, then obj + value calls obj.__add__(value).
π value: int
This means that the + operator only accepts an int on the right-hand side.
π / (positional-only marker)
The slash means all parameters before it must be passed positionally.
In this case:
-
self(always positional) -
valuemust also be provided positionally, not as a keyword argument.
So this is allowed:
obj + 3
obj.__add__(3)
But this is not allowed:
obj.__add__(value=3) # β value cannot be keyword-only
π -> int
The method returns an int.
π ...
This is a stub-style placeholder indicating βimplementation omitted.β
*args and **kwargsβ
def args_kwargs(a, b, *args, **kwargs):
print(f"a: {a}, b: {b}")
print(f"Positional arguments (*args): {args}")
print(f"Keyword arguments (**kwargs): {kwargs}")
for key, value in kwargs.items():
print(f"{key} = {value}")
# function call
args_kwargs(10, 20, 30, name="Alice", age=25)
Output:
a: 10, b: 20
Positional arguments (*args): (30,)
Keyword arguments (**kwargs): {'name': 'Alice', 'age': 25}
name = Alice
age = 25
-
*argsβ collects extra positional arguments as atuple -
**kwargsβ collects extra keyword arguments as adictionary
* and ** to unpack arguments when calling a function (Using them in reverse)β
def greet(name, age, city):
print(f"Hello, my name is {name}, I am {age} years old, and I live in {city}.")
# Using a tuple for positional args
pos_args = ("Ajay", 23, "Pala")
greet(*pos_args) # unpacks tuple into name, age, city
# Using a dictionary for keyword args
kw_args = {"name": "Ajay", "age": 23, "city": "Bengaluru"}
greet(**kw_args) # unpacks dict into name=..., age=..., city=...
Output:
Hello, my name is Ajay, I am 23 years old, and I live in Pala.
Hello, my name is Ajay, I am 23 years old, and I live in Bengaluru.
Python Object Mutabilityβ
def edit_list(lst):
lst.append(4)
lt = [1,2,3]
edit_list(lt)
print(lt) # [1,2,3,4]
- Lists are mutable β their contents can be changed in place.
- The method
.append(4)modifies the existing list object. - Inside the function,
lstrefers to the same list object aslt. - So the append operation changes the original list.
def edit_tuple(tup):
tup + (1, 2, 3)
tupl = ("a", "b" , "c")
edit_tuple(tupl)
print(tupl) # ("a", "b" , "c")
- Tuples are immutable β they cannot be changed in place.
- The expression
tup + (1, 2, 3)creates a new tuple, but does not modifytup. - We didn't assign or return this new tuple.
- So the original tuple
tuplremains unchanged.
def edit_tuple(tup):
return tup + (1, 2, 3)
tupl = ("a", "b" , "c")
tt = edit_tuple(tupl)
print(tt) # ('a', 'b', 'c', 1, 2, 3)
tup + (1, 2, 3)produces a new tuple.- This time, we
returnit. - We assigned that new tuple to
tt, thus it contains the new expanded tuple.
β Big idea
Mutable objects (list, dict, set) change in place:
- modifying them inside a function affects the original object.
Immutable objects (tuple, str, int, float, bool) cannot change:
-
operations like
+,.replace(), etc. create new objects. -
if you donβt assign or return the new object β original stays unchanged.