फ़ंक्शन — एक फ़ैसला, एक नाम
def से फ़ंक्शन लिखना, return और print का अंतर, शुरुआत में गार्ड से किनारे वाली स्थितियाँ सँभालना, और डॉकस्ट्रिंग्स।
आप कैसे सीखना चाहते हैं?
वह समस्या जिसे हम हल कर रहे हैं
दो ग्रुप के औसत नंबर निकालने हैं:
marks_a = [72, 45]
marks_b = [90, 33, 61]
print(round(sum(marks_a) / len(marks_a), 2))
print(round(sum(marks_b) / len(marks_b), 2))58.5
61.33दोनों लाइनें लगभग एक जैसी हैं, सिर्फ़ नाम अलग है। तीसरा ग्रुप आए तो तीसरी लाइन, चौथे के लिए चौथी।
समस्या लिखने की मेहनत नहीं है — कॉपी करना सस्ता है। समस्या यह है कि एक ही फ़ैसला अब कई जगह लिखा हुआ है। अगर कहा जाए कि औसत दो दशमलव की जगह एक दशमलव तक दिखाओ, तो हर लाइन ढूँढकर बदलनी पड़ेगी, और एक भी छूट गई तो प्रोग्राम दो जगह दो तरह से बर्ताव करेगा — बिना किसी एरर के।
और अगर खाली लिस्ट आ जाए? sum([]) / len([]) का मतलब शून्य से भाग, और प्रोग्राम रुक जाता है। वह जाँच हर लाइन में अलग से लगानी पड़ेगी।
फ़ंक्शन का मतलब है एक फ़ैसले को एक बार लिखकर उसे एक नाम देना। उसके बाद वह नाम बुलाने से काम हो जाता है, और बदलना हो तो सिर्फ़ एक जगह।
इस अध्याय के अंत तक आप कर पाएंगे
defसे फ़ंक्शन लिखना और कॉल करनाreturnऔरprintका फ़र्क बताना — इस अध्याय की सबसे ज़रूरी चीज़- एक फ़ंक्शन को छोटा और एक ही काम तक सीमित रखना
- किनारे वाली स्थितियाँ सँभालने के लिए शुरुआत में ही एक गार्ड लिखना
- डॉकस्ट्रिंग लिखना
पहले से क्या आना चाहिए: कॉम्प्रिहेंशन।
पहला फ़ंक्शन
def average(values):
return round(sum(values) / len(values), 2)
print(average([72, 45]))
print(average([90, 33, 61]))58.5
61.33ढाँचा:
def— “मैं एक फ़ंक्शन बना रहा हूँ”average— नाम, उसी नियम से जिससे आप वेरिएबल का नाम रखते हैं(values)— पैरामीटर, यानी अंदर डेटा आने का दरवाज़ा:और इंडेंट किया हुआ ब्लॉक — बॉडी, ठीकifयाforकी तरहreturn— नतीजा वापस भेजना
average([72, 45]) लिखने को कॉल करना कहते हैं। [72, 45] है आर्ग्युमेंट — जो सच में भेजा जा रहा है; values है पैरामीटर — अंदर का नाम। दो अलग शब्द, और एरर मैसेज में दोनों आते हैं, इसलिए फ़र्क याद रखना काम आता है।
दो खाली लाइनें। फ़ंक्शन की परिभाषा के बाद दो खाली लाइनें छोड़ना Python का चलन है। Python कम लाइनों के साथ भी चलता है, लेकिन सारा Python कोड ऐसे ही लिखा जाता है, इसलिए आदत डाल लेना अच्छा है।
return और print — एक नहीं हैं
यह इस अध्याय का सबसे ज़रूरी हिस्सा है, और नए लोगों की सबसे बड़ी उलझन।
def with_return(x):
return x * 2
def with_print(x):
print(x * 2)
a = with_return(5)
b = with_print(5)
print(a)
print(b)
print(a + 1)10
10
None
11स्क्रीन पर पहले दो 10 देखकर लगता है कि दोनों फ़ंक्शन एक जैसे हैं। ऐसा नहीं है।
with_return ने वैल्यू लौटाई, इसलिए a में 10 रखा है, और उसमें जोड़ा जा सकता है — आखिरी लाइन में 11।
with_print ने वैल्यू दिखाई और कुछ नहीं लौटाया, इसलिए b है None। स्क्रीन पर नंबर दिखा ज़रूर, लेकिन प्रोग्राम के हाथ कुछ नहीं आया। b + 1 लिखते तो TypeError आता।
नियम ऐसे याद रखें: print इंसान के लिए, return प्रोग्राम के लिए। हिसाब करने वाला फ़ंक्शन return करेगा; दिखाने का काम वहाँ होगा जहाँ से उसे कॉल किया गया। इससे वही फ़ंक्शन एक बार स्क्रीन पर प्रिंट करने के काम आ सकता है, और दूसरी बार फ़ाइल में लिखने के।
return न लिखें तो फ़ंक्शन चुपचाप None लौटाता है — यह वही None है जो append और .sort() से आता था, जिसने 12 और 13 नंबर अध्याय में परेशान किया था। अब समझ आता है कि वे None क्यों देते थे: उनका काम कुछ बदलना था, कुछ लौटाना नहीं।
return तुरंत रोक देता है
def check(mark):
if mark >= 40:
return "pass"
return "fail"
print(check(72))
print(check(20))pass
failreturn चलते ही फ़ंक्शन खत्म — बाकी लाइनें नहीं चलतीं। इसलिए यहाँ else की ज़रूरत नहीं पड़ी: पहला return चल गया तो दूसरी लाइन तक पहुँचा ही नहीं जा सकता।
यह तरीका — शर्त पूरी होते ही return — 9 नंबर अध्याय के गहरे if/else पेड़ों को सपाट कर देता है, और कोड पढ़ना बहुत आसान हो जाता है।
किनारे सँभालना — गार्ड
इस अध्याय की शुरुआत वाली समस्या याद है? खाली लिस्ट:
def average(values):
return sum(values) / len(values)
print(average([]))ZeroDivisionError: division by zeroहल फ़ंक्शन की बिल्कुल शुरुआत में बैठता है:
def average(values):
if not values:
return 0.0
return round(sum(values) / len(values), 2)
print(average([72, 45]))
print(average([]))58.5
0.0if not values — 8 नंबर अध्याय का truthiness वाला नियम फिर से: खाली लिस्ट false है, इसलिए not उसे true बना देता है। len(values) == 0 लिखने की ज़रूरत नहीं।
इसे ही गार्ड कहते हैं: असामान्य स्थिति को शुरुआत में ही सँभाल लें, फिर बाकी कोड बेफ़िक्र होकर लिखें। फ़ंक्शन यह काम आसान कर देता है — जाँच एक बार लिखी गई, और हर कॉल करने वाले को उसका फ़ायदा मिला।
क्या0.0सही जवाब है? यह बहस का विषय है। यह शून्य “किसी के नंबर नहीं हैं” और “सबको शून्य मिला” — दोनों को एक कर देता है। असली प्रोग्राम में कई बारNoneलौटाना या 24 नंबर अध्याय काraiseइस्तेमाल करना ज़्यादा ईमानदार होता है। यहाँ0.0सरलता के लिए रखा गया है — लेकिन यह जान लें कि यह एक फ़ैसला है।
डॉकस्ट्रिंग
फ़ंक्शन की पहली लाइन में एक स्ट्रिंग रखें तो वह उसका डॉक्यूमेंटेशन बन जाती है:
def average(values):
"""Return the mean of values, or 0.0 when there are none."""
if not values:
return 0.0
return round(sum(values) / len(values), 2)
print(average([1, 2, 3]))
print(average.__doc__)2.0
Return the mean of values, or 0.0 when there are none.कमेंट से इसका फ़र्क यह है कि यह प्रोग्राम के अंदर ही रहती है — एडिटर इसे दिखाता है, help(average) इसे प्रिंट करता है।
अच्छी डॉकस्ट्रिंग बताती है कि क्या लौटता है और किनारे पर क्या होता है, यह नहीं कि कोड कैसे काम करता है। कोड तो नीचे ही है।
एक पूरा उदाहरण
report.py:
# Three small functions, each doing one thing
def average(values):
"""Return the mean of values, or 0.0 when there are none."""
if not values:
return 0.0
return round(sum(values) / len(values), 2)
def grade(mark):
"""Turn a mark into a letter."""
if mark >= 80:
return "A"
if mark >= 70:
return "B"
if mark >= 40:
return "C"
return "F"
def summarise(name, marks):
"""Build one report line for a person."""
mean = average(marks)
return f"{name:<8} {len(marks):>2} papers avg {mean:>6} grade {grade(mean)}"
people = {
"rafi": [72, 88, 61],
"ahmed": [45, 38],
"dia": [],
}
for name, marks in people.items():
print(summarise(name, marks))rafi 3 papers avg 73.67 grade B
ahmed 2 papers avg 41.5 grade C
dia 0 papers avg 0.0 grade Fचार बातें ध्यान देने लायक हैं।
हर फ़ंक्शन एक काम करता है। average औसत निकालता है, grade अक्षर देता है, summarise एक लाइन बनाता है। कोई भी प्रिंट नहीं करता — प्रिंट का काम बिल्कुल नीचे वाले लूप में है, एक ही जगह। इसलिए यह रिपोर्ट फ़ाइल में लिखनी हो तो सिर्फ़ वही एक लाइन बदलनी होगी।
फ़ंक्शन फ़ंक्शन को कॉल कर रहा है। summarise कॉल कर रहा है average और grade को। यही फ़ंक्शन का असली फ़ायदा है: छोटे-छोटे भरोसेमंद टुकड़े जोड़कर बड़ा काम।
grade में कोई else नहीं है। हर return खुद ही रोक देता है, इसलिए शर्तें सपाट रहती हैं। 9 नंबर अध्याय का नियम यहाँ भी लागू है: सबसे सख्त शर्त पहले — 80 से पहले 40 लिखते तो सबको C मिलता।
dia की खाली लिस्ट ने प्रोग्राम नहीं तोड़ा। गार्ड ने 0.0 दिया, grade ने उसे F बनाया, और रिपोर्ट की लाइन सामान्य तरह से प्रिंट हुई। किनारे वाली स्थिति एक बार सँभाली गई, एक ही जगह।
जब कुछ टूट जाए
NameError: name 'greet' is not defined — जबकि फ़ंक्शन लिखा हुआ है फ़ंक्शन को उसकी def लाइन चलने से पहले कॉल किया गया है। Python फ़ाइल को ऊपर से नीचे पढ़ता है, और def चलने से पहले नाम बनता ही नहीं। सारे def ऊपर रखें, और कॉल करने वाला कोड नीचे।
TypeError: average() missing 1 required positional argument: 'values' कॉल करते समय आर्ग्युमेंट नहीं दिया गया — average() लिखा गया, average(marks) नहीं। मैसेज यह भी बताता है कि कौन-सा पैरामीटर छूटा है।
फ़ंक्शन None लौटा रहा है return लिखा ही नहीं गया, या return है लेकिन गलत इंडेंट पर — जैसे किसी if के अंदर, जिसकी शर्त पूरी नहीं होती। एक और आम वजह: जहाँ return चाहिए था वहाँ print लिख दिया गया।
फ़ंक्शन के अंदर का वेरिएबल बाहर नहीं मिल रहा यह सामान्य है — क्यों, यह 21 नंबर अध्याय का विषय है। फ़िलहाल: जो बाहर चाहिए उसे return करें।
SyntaxError — def लाइन के आखिर में कोलन नहीं है if और for की तरह, def लाइन भी कोलन पर खत्म होती है।
IndentationError: expected an indented block after function definition def लाइन के बाद कम से कम एक इंडेंट की हुई लाइन होनी चाहिए।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
फ़ंक्शन print करता है, return नहीं। दोनों लाइनें क्या प्रिंट करेंगी?
def double(x):
print(x * 2)
result = double(5)
print(result)- A10 None
- B10 10
- CNone 10
- D10
else के बिना दो return। क्या प्रिंट होगा?
def check(mark):
if mark >= 40:
return "pass"
return "fail"
print(check(72))- Apass
- Bpass fail
- Cfail
- DNone
फ़ंक्शन फ़ाइल में ही है, फिर भी क्या होगा?
print(greet("rafi"))
def greet(name):
return "hello " + name- A`SyntaxError`
- Bhello rafi
- C`TypeError`
- D`NameError` — `def` लाइन चलने से पहले ही फ़ंक्शन को कॉल किया गया
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
text_tools.py नाम की एक फ़ाइल लिखें, जिसमें चार फ़ंक्शन हों — हर एक में डॉकस्ट्रिंग हो, और कोई भी print न करे:
clean(text)— स्पेस हटाता है और छोटे अक्षरों में बदलता हैinitials(full_name)—"Rafi Ahmed"से"RA"बनाता हैword_count(text)— शब्द गिनता है, और खाली स्ट्रिंग पर0देता हैsummarise(text)— ऊपर के तीनों को कॉल करके पढ़ने लायक एक लाइन बनाकर लौटाता है
फिर फ़ाइल के नीचे कुछ स्ट्रिंग लेकर summarise कॉल करें और नतीजे प्रिंट करें — प्रिंट करने की अकेली जगह वही है।
आखिर में तीन प्रयोग करें:
word_count("")कॉल करें। गार्ड न होता तो क्या होता?summariseसेreturnहटाकर उसकी जगहprintरखें, फिर नतीजे को एक वेरिएबल में रखकर प्रिंट करें। क्या दिख रहा है, और क्यों?cleanफ़ंक्शन की कॉल को उसकेdefसे ऊपर ले जाएँ, और एरर मैसेज पढ़ें।
दूसरा प्रयोग इस अध्याय के सबसे कीमती तीन मिनट हैं। print और return का फ़र्क एक बार अपनी आँखों से देख लें, तो वह फिर कभी उलझता नहीं।
चरण 6 / 6
चुनौती — अध्याय की क्विज़
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
क्विज़ देने के लिए साइन इन करें