डिक्शनरी — key और वैल्यू की जोड़ी
नाम से वैल्यू रखना और निकालना, KeyError से बचने के लिए .get(), key जोड़ना-बदलना-हटाना, .items() से लूप चलाना, और लिस्ट key क्यों नहीं बन सकती।
आप कैसे सीखना चाहते हैं?
वह समस्या जिसे हम हल कर रहे हैं
तीन लोगों के नंबर रखने हैं — किसके कितने, यह भी।
लिस्ट से एक ही तरीक़ा है: दो लिस्ट, साथ-साथ।
names = ["rafi", "ahmed", "bilal"]
marks = [72, 45, 90]
print(names[1], marks[1])ahmed 45काम कर रहा है। लेकिन यह पूरा इंतज़ाम सिर्फ़ आपके अनुशासन पर टिका है, और यहाँ Python की कोई मदद नहीं है।
names में किसी को जोड़ा और marks में भूल गए? दोनों लिस्ट की लंबाई अलग हो जाती है, और फिर names[2] और marks[2] दो अलग लोगों की बात करते हैं। Python कुछ नहीं कहेगा। names को सॉर्ट कर दिया? रिश्ता पूरी तरह टूट जाता है, चुपचाप।
समस्या की जड़ यह है: दोनों चीज़ों के बीच का रिश्ता कहीं लिखा ही नहीं है। रिश्ता बस "एक ही इंडेक्स" है — एक संयोग, जो किसी भी पल टूट सकता है।
डिक्शनरी इस रिश्ते को कोड में लिख देती है। इंडेक्स की जगह नाम, और जोड़ी एक ही जगह बँधी हुई।
इस अध्याय के बाद आप यह कर पाएँगे
- डिक्शनरी बनाना, और key से वैल्यू निकालना
KeyErrorसे बचने के लिए.get()इस्तेमाल करना, और कब कौन सही है यह जानना- key जोड़ना, बदलना और हटाना
.keys(),.values(),.items()से घूमना- बताना कि लिस्ट key क्यों नहीं बन सकती, लेकिन टपल बन सकता है
पहले यह आना चाहिए: टपल और अनपैकिंग।
डिक्शनरी — key और वैल्यू की जोड़ी
कर्ली ब्रैकेट, और अंदर key: value की जोड़ियाँ:
marks = {"rafi": 72, "ahmed": 45, "bilal": 90}
print(marks)
print(marks["ahmed"])
print(len(marks)){'rafi': 72, 'ahmed': 45, 'bilal': 90}
45
3marks["ahmed"] — इंडेक्स नहीं, नाम। और नाम ही कोड में लिखा है, इसलिए छह महीने बाद पढ़ने पर भी समझ आता है कि क्या माँगा जा रहा है।
len() जोड़ियों की गिनती करता है, तीन।
क्रम के बारे में एक बात। Python 3.7 से डिक्शनरी जिस क्रम में चीज़ें डाली गईं वही क्रम याद रखती है, और प्रिंट करते समय भी उसी क्रम में दिखाती है। लेकिन डिक्शनरी इस्तेमाल होती है नाम से ढूँढने के लिए, पोज़िशन से नहीं —marks[0]लिखें तो Python0को एक key मानकर ढूँढेगा, और न मिलने परKeyError: 0के साथ रुक जाएगा।
जो key है ही नहीं — KeyError और .get()
marks = {"rafi": 72}
print(marks["dia"])KeyError: 'dia'KeyError का मतलब है "इस नाम की कोई key नहीं है"। लिस्ट में यही ग़लती IndexError देती — नाम अलग, ग़लती उसी तरह की।
रुकने के बजाय एक सुरक्षित जवाब चाहिए तो .get():
marks = {"rafi": 72}
print(marks.get("dia"))
print(marks.get("dia", 0))
print(marks.get("rafi", 0))None
0
72दूसरा आर्गुमेंट है "न मिले तो यह दे देना"। न दें तो None आता है।
कब कौन? key का होना ज़रूरी है तो marks["rafi"] लिखिए — न हो तो वह एक बग है, और KeyError उसे तुरंत पकड़वा देता है। key का न होना सामान्य बात है तो .get() लिखिए। हर जगह .get() लिखते फिरेंगे तो ग़लत डेटा भी चुपचाप निकल जाएगा, और वही तो आप ढूँढना चाहते थे।
जोड़ना, बदलना, हटाना
marks = {"rafi": 72}
marks["dia"] = 88
marks["rafi"] = 75
print(marks)
del marks["rafi"]
print(marks){'rafi': 75, 'dia': 88}
{'dia': 88}एक ही लाइन दो काम करती है: key न हो तो जुड़ जाती है, हो तो वैल्यू बदल जाती है। "जोड़ो" का कोई अलग मेथड नहीं है।
और यहीं से एक ज़रूरी नियम आता है — एक key सिर्फ़ एक बार हो सकती है:
marks = {"rafi": 72, "rafi": 90}
print(marks){'rafi': 90}कोई एरर नहीं। दूसरी ने पहली को चुपचाप मिटा दिया। फ़ाइल से डेटा पढ़ते समय यह अक्सर होता है, और रिकॉर्ड खोने की यह एक आम वजह है।
in key ढूँढता है, वैल्यू नहीं
marks = {"rafi": 72, "ahmed": 45}
print("rafi" in marks)
print(72 in marks)True
False72 वैल्यू के रूप में मौजूद है, लेकिन in सिर्फ़ key में ढूँढता है। वैल्यू में ढूँढना हो तो साफ़-साफ़ कहना पड़ता है: 72 in marks.values()।
घूमना — तीन तरह से
marks = {"rafi": 72, "ahmed": 45}
for name in marks:
print(name)
print("---")
for name, mark in marks.items():
print(name, mark)
print("---")
print(list(marks.keys()))
print(list(marks.values()))rafi
ahmed
---
rafi 72
ahmed 45
---
['rafi', 'ahmed']
[72, 45]पहला ध्यान देने लायक़ है: for name in marks लिखने पर key मिलती है, वैल्यू नहीं। पहली बार यह सबको हैरान करता है।
दोनों चाहिए तो .items(), जो हर चक्कर में एक टपल देता है — और name, mark उसे अनपैक कर लेता है। पिछले अध्याय की अनपैकिंग सबसे ज़्यादा यहीं काम आती है।
वैल्यू से हिसाब करना हो तो .values():
marks = {"rafi": 72, "ahmed": 45, "bilal": 90}
print(sum(marks.values()))
print(max(marks.values()))
print(round(sum(marks.values()) / len(marks), 2))207
90
69.0कौन-सी चीज़ key बन सकती है
key बनने के लिए चीज़ का न बदलने वाला (immutable) होना ज़रूरी है। स्ट्रिंग, नंबर, टपल — चलते हैं। लिस्ट नहीं चलती:
d = {}
d[["a", "b"]] = 1TypeError: unhashable type: 'list'"Unhashable" शब्द समझाने लायक़ है। डिक्शनरी इतनी तेज़ी से इसलिए ढूँढ पाती है क्योंकि वह हर key से एक नंबर (hash) निकालकर रखती है और उस नंबर से सीधे सही जगह पहुँच जाती है। key बाद में बदल जाए तो वह हिसाब ग़लत हो जाता, और चीज़ खो जाती। इसलिए Python बदलने वाली किसी चीज़ को key बनने ही नहीं देता।
टपल बदला नहीं जा सकता, इसलिए टपल बढ़िया key है:
grid = {}
grid[(0, 0)] = "start"
grid[(1, 2)] = "tree"
print(grid)
print(grid[(1, 2)]){(0, 0): 'start', (1, 2): 'tree'}
treeपिछले अध्याय में टपल के न बदलने को फ़ायदा कहा गया था। यह उसका पहला व्यावहारिक सबूत है।
सबसे काम का पैटर्न — गिनना
words = ["pen", "bag", "pen", "ink", "pen"]
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
print(counts){'pen': 3, 'bag': 1, 'ink': 1}लाइन को अंदर से पढ़िए: counts.get(word, 0) कह रहा है "इस शब्द की अभी तक की गिनती दो, पहले से न हो तो शून्य मानो", फिर उसमें एक जोड़कर वापस रख दिया जाता है।
.get() की डिफ़ॉल्ट वैल्यू ही यहाँ पूरा काम कर रही है — वह न होती तो हर नए शब्द पर KeyError आता, और if word in counts: लिखकर दो रास्ते संभालने पड़ते। एक लाइन का यह पैटर्न आप बहुत बार लिखेंगे।
एक पूरा उदाहरण
marks.py:
# A dictionary keeps a name attached to its value
marks = {"rafi": 72, "ahmed": 45, "bilal": 90, "dia": 88}
print("Everyone:")
for name, mark in marks.items():
status = "pass" if mark >= 40 else "fail"
print(f" {name:<8} {mark:>3} {status}")
print()
print("Count :", len(marks))
print("Total :", sum(marks.values()))
print("Average :", round(sum(marks.values()) / len(marks), 2))
print("Highest :", max(marks.values()))
best = max(marks, key=marks.get)
print("Best :", best, marks[best])
print("Has dia :", "dia" in marks)
print("Missing :", marks.get("nadia", "not recorded"))
marks["dia"] = 91
marks["nadia"] = 60
del marks["ahmed"]
print()
print("After edits:", marks)Everyone:
rafi 72 pass
ahmed 45 pass
bilal 90 pass
dia 88 pass
Count : 4
Total : 295
Average : 73.75
Highest : 90
Best : bilal 90
Has dia : True
Missing : not recorded
After edits: {'rafi': 72, 'bilal': 90, 'dia': 91, 'nadia': 60}तीन बातें ध्यान देने लायक़ हैं।
status = "pass" if mark >= 40 else "fail" — यह एक शर्त को एक लाइन में लिखने का तरीक़ा है, जिसे ऐसे पढ़ते हैं: "mark >= 40 हो तो "pass", नहीं तो "fail""। अध्याय 9 का चार लाइन वाला if/else यहाँ बस एक वैल्यू चुन रहा है, इसलिए एक लाइन काफ़ी है। बड़े फ़ैसलों के लिए पूरा if लिखिए — यह सिर्फ़ "दो में से एक वैल्यू" वाले काम के लिए है।
max(marks, key=marks.get) — अध्याय 13 का key=, नए काम में। (यहाँ key= max के आर्गुमेंट का नाम है, डिक्शनरी की key नहीं।) max(marks) key में से सबसे बड़ी देता, यानी वर्णमाला में आख़िरी नाम। key=marks.get कह रहा है कि हर key की तुलना उसकी वैल्यू से करो — इसलिए सबसे ज़्यादा नंबर वाला नाम आता है। ध्यान दीजिए, सबसे ज़्यादा नंबर पाना आसान है (max(marks.values())), लेकिन वह किसका है यह जानने के लिए यह तरीक़ा चाहिए।
आख़िरी लाइन का क्रम। dia पहले से थी, इसलिए उसकी वैल्यू बदली लेकिन जगह नहीं बदली। nadia नई है, इसलिए आख़िर में जुड़ी। और ahmed मिट गया। डिक्शनरी डालने का क्रम याद रखती है — कोई वैल्यू बदलने से वह क्रम नहीं हिलता।
कुछ टूटी हुई हालतें और उनका हल
KeyError: 'dia' इस नाम की कोई key नहीं है। स्पेलिंग और छोटे-बड़े अक्षर मिलाकर देखिए — "Rafi" और "rafi" दो अलग key हैं। फ़ाइल से पढ़ी गई key के आख़िर में अक्सर एक स्पेस लगा रहता है; print(list(d.keys())) से देखें तो कोटेशन के अंदर वह पकड़ में आ जाता है। key का न होना सामान्य हो तो .get() इस्तेमाल कीजिए।
TypeError: unhashable type: 'list' एक लिस्ट को key बनाने की कोशिश। टपल इस्तेमाल कीजिए — tuple(my_list) उसे बना देता है।
for x in my_dict लिखने पर वैल्यू नहीं मिल रही मिलनी भी नहीं चाहिए — वह key देता है। वैल्यू के लिए .values(), दोनों के लिए .items()।
दोनों key एक ही थीं, एक रिकॉर्ड खो गया एक key सिर्फ़ एक बार होती है, और बाद वाली पहले वाली को चुपचाप बदल देती है। एक ही नाम से कई रिकॉर्ड रखने हों तो वैल्यू के रूप में एक लिस्ट रखिए — यह अध्याय 17 का विषय है।
KeyError: 0 my_dict[0] लिखा गया है, लिस्ट की तरह पहला आइटम माँगते हुए। डिक्शनरी में पोज़िशन जैसा कुछ नहीं होता; 0 को एक key की तरह ही ढूँढा जाता है, और ऐसी key न हो तो KeyError: 0 आता है। पहली जोड़ी सच में चाहिए तो list(my_dict.items())[0] लिखिए।
डिक्शनरी पर .sort() नहीं चलता सही बात — डिक्शनरी में .sort() नहीं है। sorted(d.items()) एक सॉर्ट की हुई लिस्ट देता है, और आमतौर पर वही चाहिए होता है।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
एक डिक्शनरी पर सीधे लूप चलाया गया है। क्या प्रिंट होगा?
marks = {"rafi": 72, "ahmed": 45}
for name in marks:
print(name)- Arafi 72 ahmed 45
- Brafi ahmed
- C72 45
- D('rafi', 72) ('ahmed', 45)
जो key है ही नहीं, वह माँगी गई है। क्या होगा, और सुरक्षित विकल्प क्या है?
marks = {"rafi": 72}
print(marks["dia"])- A`None` प्रिंट होता है
- Bएक ख़ाली लाइन प्रिंट होती है
- C`KeyError` — सुरक्षित विकल्प `marks.get("dia")` है, जो `None` देता है
- D`IndexError`
गिनती वाला पैटर्न। क्या प्रिंट होगा?
words = ["pen", "bag", "pen"]
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
print(counts)- Aएक `KeyError`
- B{'pen': 2, 'bag': 1}
- C{'pen': 1, 'bag': 1}
- D{'pen': 3, 'bag': 1}
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
stock.py नाम की एक फ़ाइल लिखिए, जिसमें कम से कम छह प्रोडक्ट की एक डिक्शनरी हो — प्रोडक्ट का नाम key, और क़ीमत वैल्यू।
फिर:
- हर प्रोडक्ट और उसकी क़ीमत सीधे कॉलम में प्रिंट कीजिए
- कुल, औसत, सबसे ज़्यादा और सबसे कम क़ीमत प्रिंट कीजिए
- सबसे महँगे प्रोडक्ट का नाम निकालिए — सिर्फ़ क़ीमत नहीं
- एक नया प्रोडक्ट जोड़िए, एक की क़ीमत बदलिए, और एक हटाइए; फिर पूरी डिक्शनरी दोबारा प्रिंट कीजिए
.get()से ऐसे प्रोडक्ट की क़ीमत माँगिए जो है ही नहीं, और डिफ़ॉल्ट के रूप में एक मैसेज दीजिए
फिर एक गिनती वाला प्रोग्राम लिखिए: एक लिस्ट में कुछ शब्द रखिए (कुछ एक से ज़्यादा बार), और counts.get(word, 0) + 1 पैटर्न से हर शब्द कितनी बार है, गिनकर प्रिंट कीजिए।
आख़िर में जानबूझकर तोड़िए: जो key है ही नहीं उसे स्क्वेयर ब्रैकेट से माँगिए, और एक लिस्ट को key बनाने की कोशिश कीजिए। दो अलग एरर आएँगे — कौन-सा क्यों, खुद को समझाइए।
चरण 6 / 6
चुनौती — अध्याय की क्विज़
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
क्विज़ देने के लिए साइन इन करें