*args & **kwargs
*args function ko variable number ke POSITIONAL arguments accept karne deta hai — andar ek tuple ke roop mein milte hain. **kwargs variable number ke KEYWORD arguments accept karta hai — andar ek dictionary ke roop mein milte hain.
Ye bahut common hai "wrapper" functions mein jo kisi doosre function ko forward karte hain, chahe uske exact parameters kuch bhi hon — decorators (aage aayega) isi pattern par heavily depend karte hain.
def add_all(*args): # kitne bhi positional args
return sum(args)
print(add_all(1, 2, 3, 4)) # 10
def print_info(**kwargs): # kitne bhi keyword args
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Aarav", age=20)
# name: Aarav
# age: 20
def flexible(a, b, *args, **kwargs): # sab combine kar sakte ho
print(a, b, args, kwargs)
flexible(1, 2, 3, 4, x=5, y=6)
# 1 2 (3, 4) {'x': 5, 'y': 6}- *args = variable positional arguments → tuple
- **kwargs = variable keyword arguments → dictionary
- Wrapper functions/decorators mein bahut common
* aur ** sirf function DEFINE karte waqt "collect" nahi karte — function CALL karte waqt bhi use ho sakte hain, taaki ek existing list/dict ko individual arguments mein "unpack" kar sako.
def add_three(a, b, c):
return a + b + c
numbers = [1, 2, 3]
print(add_three(*numbers)) # unpacks to add_three(1, 2, 3)
data = {"a": 1, "b": 2, "c": 3}
print(add_three(**data)) # unpacks to add_three(a=1, b=2, c=3)Python 3.8+ mein / aur * function signature mein special markers hain — / se pehle wale parameters SIRF positional ho sakte hain, * ke baad wale SIRF keyword. Ye API design ko explicit control deta hai.
def func(a, b, /, c, d, *, e, f):
# a, b = positional-only
# c, d = positional ya keyword dono
# e, f = keyword-only
pass
func(1, 2, 3, d=4, e=5, f=6) # valid
# func(a=1, b=2, c=3, d=4, e=5, f=6) # ERROR: a, b positional-only hain