Home › Hindi › *args और **kwargs Hindi में
*args और **kwargs — कितने भी arguments लेने वाले functions
🌐 यह page Hindi में है · Read the English functions guide →
*args**kwargsUnpackingDefault arguments
एक तारे और दो तारे का फर्क
*args अतिरिक्त positional arguments को एक tuple में बाँधता है। **kwargs अतिरिक्त keyword arguments को एक dict में। नाम कोई भी हो सकता है — *values भी चलेगा — पर convention यही है और हर Python programmer यही पढ़ने की उम्मीद करता है।
def show(*args, **kwargs):
print("args :", args, type(args).__name__)
print("kwargs:", kwargs, type(kwargs).__name__)
show(1, 2, 3)
# args : (1, 2, 3) tuple
# kwargs: {} dict
show(1, 2, name="Asha", city="Delhi")
# args : (1, 2) tuple
# kwargs: {'name': 'Asha', 'city': 'Delhi'} dict
show()
# args : () tuple — खाली, error नहीं
# kwargs: {} dictदोनों हमेशा भरे हुए नहीं होते। कोई अतिरिक्त argument न मिले तो args खाली tuple और kwargs खाली dict होता है — None नहीं। इसीलिए इन पर सीधा loop चलाना सुरक्षित है।
Parameters का सही क्रम
क्रम तय है और बदला नहीं जा सकता:
def f(positional, /, normal, *args, keyword_only, **kwargs):
pass
# ^^^^^^^^^^ ^^^^^^ ^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^
# सिर्फ positional आम बाकी सब keyword ज़रूरी बाकी सब
# व्यवहार में ज़्यादातर यही दिखता है
def log(message, *args, level="INFO", **kwargs):
print(f"[{level}] {message}", args, kwargs)
log("saved", 42, True, level="DEBUG", user="asha")
# [DEBUG] saved (42, True) {'user': 'asha'}# क्रम गलत — SyntaxError
def f(*args, normal, **kwargs): # *args के बाद वाला keyword-only है,
pass # ये सही है, पर default के बिना
# हर call में उसे देना पड़ेगा
Unpacking — तारा उलटी दिशा में
यही तारे definition से बाहर भी काम करते हैं, बस उल्टा। Definition में बाँधते हैं, call में खोलते हैं:
nums = [1, 2, 3]
config = {"host": "localhost", "port": 8080}
total(*nums) # total(1, 2, 3)
connect(**config) # connect(host="localhost", port=8080)
# दोनों साथ
def connect(host, port, timeout=30, retries=3):
...
args = ["localhost", 8080]
extra = {"retries": 5}
connect(*args, **extra) # connect("localhost", 8080, retries=5)
# unpacking definition में नहीं, list/tuple banane me bhi
first, *rest = [1, 2, 3, 4] # first=1, rest=[2, 3, 4]
merged = [*nums, 4, 5] # [1, 2, 3, 4, 5]
combined = {**config, "port": 9090} # port overrideआखिरी दो lines असली code में सबसे ज़्यादा काम आती हैं — एक list या dict की copy बनाकर एक चीज़ बदलना, मूल को छुए बिना।
असली use case — wrapper और decorator
*args, **kwargs का सबसे बड़ा use case तब है जब आप किसी और function को लपेट रहे हों और उसके signature की परवाह न करना चाहें:
import functools, time
def timed(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = fn(*args, **kwargs) # सब कुछ ज्यों का त्यों आगे
print(f"{fn.__name__}: {time.perf_counter() - start:.4f}s")
return result
return wrapper
@timed
def fetch(url, retries=3, **opts):
...
fetch("https://x", retries=5, timeout=10) # signature बदलने पर wrapper नहीं टूटेगाfunctools.wraps भूल मत जाना — उसके बिना लपेटे गए function का नाम और docstring wrapper के हो जाते हैं, और debugging बहुत भ्रमित करने वाली बन जाती है।
आम गलतियाँ
argsको list समझ लेना। वो tuple है, इसलिएargs.append(x)परAttributeErrorमिलेगा। बदलना हो तोlist(args)बनाओ।- Do तारे एक जगह लगाना।
f(**a, **b)पुराने Python मेंSyntaxErrorथा; नए में चलता है पर duplicate keys चुपचाप overwrite हो जाते हैं। - Keyword-only parameter को positional भेजना।
*के बाद वाले arguments सिर्फ नाम से भेजे जा सकते हैं। - हर function पर
*args, **kwargsलगा देना। ये signature को बेमतलब बना देता है — caller को पता ही नहीं चलता क्या भेजना है, और typo चुपचापkwargsमें चला जाता है।
def connect(host, port, **kwargs):
...
connect("localhost", 8080, timout=30) # typo — कोई error नहीं!
# kwargs = {'timout': 30}, और timeout चुपचाप default पर रह गया
# बचाव: keyword-only parameters नाम स्पष्ट कर देते हैं
def connect(host, port, *, timeout=30, retries=3):
...
connect("localhost", 8080, timout=30) # TypeError: unexpected keyword
Default arguments का trap
यह *args/**kwargs से सीधा जुड़ा नहीं, पर एक ही जगह आता है और सबसे ज़्यादा नुकसान करता है:
def add_item(item, box=[]): # ❌ list एक ही बार बनती है,
box.append(item) # definition के समय — हर call उसे साझा करता है
return box
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] — पिछली call की गंदगी!
def add_item(item, box=None): # ✅
if box is None:
box = []
box.append(item)
return boxनियम याद रख लो: default value function के definition के समय एक बार evaluate होती है, हर call पर नहीं। इसलिए mutable default ([], {}, set()) हमेशा गलत है। None use करो और अंदर बनाओ।
क्या ये ज़रूरी है?
नहीं, और अक्सर ये नुकसानदेह है। तीन जगह ये सही है: wrapper और decorator, किसी और API को आगे बढ़ाना (जैसे logging), और CLI arguments जैसे अनिश्चित इनपुट। बाकी हर जगह साफ-साफ named parameters लिखो।
# ज़रूरत नहीं है
def add_all(*nums):
return sum(nums)
# बेहतर — caller को पता चलता है क्या भेजना है
def add_all(nums: list[float]) -> float:
return sum(nums)
# पर यहाँ सही है
def run(command, *args, env=None, **popen_kwargs):
return subprocess.run([command, *args], env=env, **popen_kwargs)
🛠️ Practice करो (free, browser में)
पढ़ना काफी नहीं — यही bug खुद fix करके देखो। नीचे के problems browser में ही चलते हैं, कोई install नहीं, कोई login नहीं।
- Tuple unpacking with functions — तारा उलटी दिशा में।
- Mutable default argument trap — सबसे खतरनाक default value।
- Calling a function with too few arguments — arguments की गिनती की गलती।
अक्सर पूछे जाने वाले सवाल
*args और **kwargs क्या हैं?
*args अतिरिक्त positional arguments को एक tuple में बाँधता है और **kwargs अतिरिक्त keyword arguments को dict में। नाम कोई भी हो सकता है, पर यही convention है। दोनों खाली भी हो सकते हैं — तब () और {} मिलते हैं, None नहीं।
क्या args एक list है?
नहीं, tuple है। इसलिए args.append(x) पर AttributeError मिलेगा। Tuple immutable है, क्योंकि function को अपने arguments बदलने नहीं चाहिए। बदलना हो तो list(args) बनाओ।
Parameters का सही क्रम क्या है?
positional, फिर आम parameters, फिर *args, फिर keyword-only parameters, और अंत में **kwargs। ये क्रम तय है और बदला नहीं जा सकता।
Unpacking क्या है?
वही तारे उलटी दिशा में। Definition में args और kwargs बाँधते हैं; call में *list और **dict खोलते हैं। जैसे total(*[1,2,3]) यानी total(1,2,3)।
क्या हर function में इन्हें लगाना चाहिए?
नहीं। ये signature को बेमतलब बना देते हैं और typo चुपचाप kwargs में चला जाता है। सिर्फ wrapper, decorator, forwarding API और अनिश्चित इनपुट के लिए use करो — बाकी जगह named parameters लिखो।