अध्याय 20

फ़ंक्शन के तर्क — नाम, डिफ़ॉल्ट और स्टार्स

नाम से तर्क भेजना, डिफ़ॉल्ट मान और उनके क्रम का नियम, *args और **kwargs, और कॉल करते समय लिस्ट या डिक्शनरी को अनपैक करना।

32 मिनटPython 3.12
  1. 1समस्या
  2. 2समझें
  3. 3उदाहरण
  4. 4अनुमान
  5. 5स्वयं करें
  6. 6चुनौती

वह समस्या जिसे हम हल कर रहे हैं

पिछले अध्याय के फ़ंक्शंस को केवल एक ही तरीके से कॉल किया जा सकता था: जितने पैरामीटर हैं उतने तर्क, ठीक उसी क्रम में।

व्यावहारिक रूप में यह पर्याप्त नहीं है। एक ऑर्डर के लिए एक फ़ंक्शन पर विचार करें:

python
def order(item, quantity):
    return f"{quantity} x {item}"


print(order("pen", 3))
print(order(3, "pen"))
text
3 x pen
pen x 3

दूसरी पंक्ति ने कोई त्रुटि नहीं दी — इसने केवल एक अर्थहीन उत्तर दिया। जब दो पैरामीटर एक ही प्रकार के होते हैं, तो पायथन के पास यह बताने का कोई तरीका नहीं होता कि क्रम उलट गया था।

और यदि लगभग प्रत्येक ऑर्डर एक ही वस्तु के लिए हो? आप हर बार 1 टाइप करेंगे। यदि किसी फ़ंक्शन में चार वैकल्पिक सेटिंग्स हैं? आप हर बार चारों पास करेंगे, जिनमें वे भी शामिल हैं जिन्हें आप नहीं बदल रहे हैं।

यह अध्याय तर्कों (arguments) को पास करने के शेष तरीकों के बारे में है: नाम से, डिफ़ॉल्ट के साथ, और अज्ञात संख्या में।

इस मिशन के अंत तक आप सीखेंगे

  • नाम द्वारा तर्क पास करना, और यह तय करना कि आपको कब ऐसा करना चाहिए
  • डिफ़ॉल्ट मान देना, और उनके क्रम के नियम का पालन करना
  • *args के साथ किसी भी संख्या में तर्क स्वीकार करना
  • **kwargs के साथ किसी भी नाम के तर्क स्वीकार करना
  • कॉल में एक सूची या डिक्शनरी को अनपैक करना

पूर्वापेक्षाएँ: फ़ंक्शंस — एक निर्णय, एक नाम.


नाम द्वारा पास करना (Keyword Arguments)

क्रम याद रखने के बजाय, नाम लिखें:

python
def order(item, quantity):
    return f"{quantity} x {item}"


print(order(quantity=3, item="pen"))
text
3 x pen

नामों के साथ, क्रम कोई मायने नहीं रखता — quantity पहले लिखा गया था और फिर भी सही जगह पर पहुँचा।

आपको कब ऐसा करना चाहिए? जब तर्क स्वयं स्पष्ट न हो। order("pen", 3) ठीक लगता है। लेकिन send(True, False) कुछ नहीं बताता, जबकि send(retry=True, verbose=False) स्पष्ट बताता है। नियम के रूप में: True/False या एक साधारण संख्या पास करते समय उनका नाम लिखें।

डिफ़ॉल्ट मान (Default Values)

python
def order(item, quantity=1):
    return f"{quantity} x {item}"


print(order("pen"))
print(order("pen", 5))
print(order("pen", quantity=5))
text
1 x pen
5 x pen
5 x pen

quantity=1 कहता है "यदि कोई अन्यथा न कहे तो एक मान लें"।

एक नियम का पालन किया जाना चाहिए: डिफ़ॉल्ट मान वाले पैरामीटर हमेशा अंत में आते हैं।

text
def order(quantity=1, item):
    return item
text
SyntaxError: parameter without a default follows parameter with a default

कारण स्पष्ट है: order("pen") दिए जाने पर, पायथन कैसे जानेगा कि "pen" किस पैरामीटर के लिए है?

किसी भी संख्या में तर्क — *args

python
def total(*prices):
    return sum(prices)


print(total(15, 60))
print(total(15, 60, 850))
print(total())
text
75
925
0

*prices में स्टार कहता है "यहाँ शेष सभी स्थितीय तर्कों (positional arguments) को इकट्ठा करें"।

इकट्ठा की गई वस्तु क्या है?

python
def show(*things):
    print(type(things))
    print(things)


show(1, "two")
text
<class 'tuple'>
(1, 'two')

एक टपल।

किसी भी नाम के तर्क — **kwargs

python
def describe(**fields):
    print(type(fields))
    for key, value in fields.items():
        print(f"{key}: {value}")


describe(item="pen", quantity=3)
text
<class 'dict'>
item: pen
quantity: 3

दो स्टार नाम से पास किए गए तर्कों को इकट्ठा करते हैं, और परिणाम एक डिक्शनरी होता है।

एक स्टार एक टपल देता है, दो स्टार एक डिक्शनरी देते हैं।

क्रम निश्चित है

साथ में लिखे जाने पर क्रम है: *साधारण पैरामीटर, फिर `args, फिर डिफ़ॉल्ट वाले, फिर kwargs`।

text
def f(a, *args, b=1, **kwargs):

कॉल में अनपैकिंग

स्टार्स का उपयोग कॉल के समय भी किया जा सकता है, जहाँ वे विपरीत काम करते हैं:

python
def order(item, quantity):
    return f"{quantity} x {item}"


values = ["pen", 3]
fields = {"item": "bag", "quantity": 2}

print(order(*values))
print(order(**fields))
text
3 x pen
2 x bag

*values सूची को अनपैक करता है। **fields डिक्शनरी को अनपैक करता है, और इसकी कीज़ पैरामीटर नामों से मेल खानी चाहिए।


एक संपूर्ण उदाहरण

invoice.py:

python
# तर्क, उसी क्रम में जिसकी पायथन अपेक्षा करता है
def invoice(customer, *items, currency="unit", discount=0.0, **extra):
    total = sum(price for _, price in items)
    after = total * (1 - discount)

    lines = [f"Invoice for {customer}"]
    for name, price in items:
        lines.append(f"  {name:<10} {price:>8.2f} {currency}")
    lines.append(f"  {'subtotal':<10} {total:>8.2f} {currency}")
    if discount:
        lines.append(f"  {'discount':<10} {discount * 100:>7.0f}%")
    lines.append(f"  {'total':<10} {after:>8.2f} {currency}")
    for key, value in extra.items():
        lines.append(f"  note {key}: {value}")
    return "
".join(lines)


print(invoice("rafi", ("pen", 15.0), ("bag", 850.0)))
print()
print(invoice("dia", ("ink", 120.0), discount=0.1, reference="A-77"))
text
Invoice for rafi
  pen           15.00 unit
  bag          850.00 unit
  subtotal     865.00 unit
  total        865.00 unit

Invoice for dia
  ink          120.00 unit
  subtotal     120.00 unit
  discount        10%
  total        108.00 unit
  note reference: A-77

चार बातें ध्यान देने योग्य हैं:

customer आवश्यक है और बाकी सब वैकल्पिक है।

discount=0.0 एक डिफ़ॉल्ट है और शर्त को सरल करता है।

`extra` उन चीज़ों को अवशोषित करता है जिनके बारे में फ़ंक्शन को पहले से नहीं पता है।**


जब यह टूटता है

SyntaxError: parameter without a default follows parameter with a default डिफ़ॉल्ट वाले पैरामीटर को आवश्यक पैरामीटर से पहले रखा गया था।

TypeError: order() takes 2 positional arguments but 3 were given बहुत अधिक तर्क दिए गए।

TypeError: order() got an unexpected keyword argument 'qty' नाम से पास किया गया, लेकिन उस नाम का कोई पैरामीटर नहीं है।

TypeError: order() got multiple values for argument 'item' एक ही पैरामीटर दो बार दिया गया, एक बार स्थिति से और एक बार नाम से।