Python में डिक्शनरी (dict): बनाना, मेथड, लूप, सॉर्टिंग और frozendict
Python की डिक्शनरी (dict) «कुंजी — मान» के जोड़ों का बदले जा सकने वाला संग्रह है, जो कुंजी से मान लगभग तुरंत ढूँढती है; बनती है कर्ली ब्रैकेट से, जैसे {"कॉफ़ी": 250}, या dict() फ़ंक्शन से। कुंजियाँ अनूठी और हैश होने योग्य होनी चाहिए, Python 3.7 से डालने का क्रम बचा रहता है, और 3.15 में बिल्ट-इन न बदला जा सकने वाला रूप frozendict है।
Python की डिक्शनरी (dict) «कुंजी — मान» के जोड़ों का संग्रह है, जिसमें मान कुंजी से चाहे कितनी भी प्रविष्टियाँ हों, लगभग तुरंत मिल जाता है। श्रेणी के अनुसार ख़र्च जोड़ना, सेटिंग्स रखना या उपयोगकर्ता को id से तेज़ी से खोजना हो — डिक्शनरी ही काम आती है। नीचे python dict से जुड़ी सारी ज़रूरी बातें हैं: बनाना, मेथड, लूप, सॉर्टिंग, मिलाना, और Python 3.15 का नया frozendict।
Python में डिक्शनरी क्या है
डिक्शनरी में जोड़े रहते हैं, और कुंजी अनूठी होती है: किसी मौजूदा कुंजी पर नया मान लिखें, तो पुराना मान बदल जाता है। अंदर से यह हैश टेबल है, इसलिए कुंजी से खोजना, जोड़ना और हटाना पूरी सूची में एक-एक करके देखने के बजाय औसतन स्थिर समय में होता है।
कुंजी केवल हैश होने योग्य ऑब्जेक्ट हो सकती है: स्ट्रिंग, संख्या, न बदले जा सकने वाले मानों वाला टपल। लिस्ट कुंजी नहीं बन सकती — TypeError: unhashable type: 'list' आएगा। मान किसी भी प्रकार के हो सकते हैं, जिनमें दूसरी डिक्शनरी और लिस्ट भी शामिल हैं।
Python 3.7 से डिक्शनरी डालने का क्रम पक्का याद रखती है: लूप करने पर कुंजियाँ उसी क्रम में मिलती हैं, जिसमें आपने उन्हें जोड़ा था।
डिक्शनरी कैसे बनाएँ
डिक्शनरी बनाने के कई तरीके हैं, और असली कोड में ये सभी दिखते हैं।
spent = {"खाना": 1200, "टैक्सी": 450} # शाब्दिक (literal)
empty = {} # खाली डिक्शनरी
also_empty = dict() # वही, dict फ़ंक्शन से
user = dict(name="अनीता", age=30) # नाम वाले आर्गुमेंट
pairs = dict([("a", 1), ("b", 2)]) # जोड़ों की सूची से
keys = dict.fromkeys(["x", "y"], 0) # {'x': 0, 'y': 0}
ध्यान दें: खाली कर्ली ब्रैकेट {} खाली डिक्शनरी बनाता है, सेट नहीं। खाली सेट सिर्फ़ set() से बनता है।
दो सूचियों से डिक्शनरी बनाने का सुविधाजनक तरीका zip है:
names = ["खाना", "टैक्सी", "सिनेमा"]
sums = [1200, 450, 600]
spent = dict(zip(names, sums))
print(spent) # {'खाना': 1200, 'टैक्सी': 450, 'सिनेमा': 600}
कुंजी से मान पढ़ना: d[k] और get
मान वर्गाकार ब्रैकेट से पढ़ा जाता है। कुंजी न हो तो Python KeyError देता है। त्रुटि से बचने के लिए get मेथड लें: वह None या दिया गया डिफ़ॉल्ट मान लौटाता है।
spent = {"खाना": 1200}
print(spent["खाना"]) # 1200
print(spent.get("सिनेमा")) # None
print(spent.get("सिनेमा", 0)) # 0
spent["सिनेमा"] # KeyError: 'सिनेमा'
कुंजी मौजूद है या नहीं, यह in से जाँचा जाता है: "खाना" in spent True लौटाएगा। यह सिर्फ़ कुंजियाँ जाँचता है, मान नहीं। मानों के लिए लिखें 1200 in spent.values()।
जोड़ना, बदलना और हटाना
रिकॉर्ड जोड़ना या अपडेट करना एक असाइनमेंट की पंक्ति है। गिनती के लिए get के साथ यह जोड़ी बहुत काम की है:
spent = {}
for category, amount in [("खाना", 250), ("टैक्सी", 300), ("खाना", 400)]:
spent[category] = spent.get(category, 0) + amount
print(spent) # {'खाना': 650, 'टैक्सी': 300}
कुंजी हटाने के लिए del d[k] (कुंजी न हो तो KeyError) या d.pop(k, default) है, जो मान भी लौटाता है। पूरी डिक्शनरी खाली करने के लिए d.clear()। लंबाई, यानी जोड़ों की संख्या, len(d) से मिलती है।
डिक्शनरी के मेथड: संक्षिप्त सूची
| मेथड | क्या करता है |
|---|---|
get(k, default) | कुंजी का मान, या बिना त्रुटि के default |
setdefault(k, default) | मान लौटाता है; कुंजी न हो तो पहले default लिख देता है |
update(other) | दूसरी डिक्शनरी के जोड़े जोड़ता और बदलता है |
pop(k, default) | कुंजी हटाता है और मान लौटाता है |
popitem() | आख़िरी जोड़ा हटाकर लौटाता है |
keys(), values(), items() | कुंजियों, मानों और जोड़ों के व्यू |
copy() | सतही प्रतिलिपि |
clear() | डिक्शनरी खाली करना |
fromkeys(keys, value) | एक ही मान वाली नई डिक्शनरी |
setdefault: मानों के रूप में लिस्ट भरना
जब मान लिस्ट हों और डेटा को समूहित करना हो, तब setdefault काम आता है:
groups = {}
for item, cat in [("कॉफ़ी", "खाना"), ("मेट्रो", "यात्रा"), ("पिज़्ज़ा", "खाना")]:
groups.setdefault(cat, []).append(item)
print(groups) # {'खाना': ['कॉफ़ी', 'पिज़्ज़ा'], 'यात्रा': ['मेट्रो']}
update: डिक्शनरी अपडेट करना
update डिक्शनरी को उसी जगह बदलता है: नई कुंजियाँ जुड़ती हैं, और मेल खाने वाली कुंजियों के मान बदल दिए जाते हैं।
cfg = {"debug": False, "lang": "hi"}
cfg.update({"debug": True, "theme": "dark"})
print(cfg) # {'debug': True, 'lang': 'hi', 'theme': 'dark'}
defaultdict: डिफ़ॉल्ट मान वाली डिक्शनरी
collections.defaultdict dict का उपवर्ग है, जो किसी गायब कुंजी तक पहुँचने पर फ़ैक्टरी से मान खुद बना देता है। गिनती और समूहीकरण का कोड इससे छोटा हो जाता है।
from collections import defaultdict
spent = defaultdict(int)
for cat, amount in [("खाना", 250), ("टैक्सी", 300), ("खाना", 400)]:
spent[cat] += amount
print(dict(spent)) # {'खाना': 650, 'टैक्सी': 300}
groups = defaultdict(list)
groups["खाना"].append("कॉफ़ी")
सिर्फ़ गिनती के लिए collections.Counter भी है: Counter(["a", "b", "a"]) देगा Counter({'a': 2, 'b': 1})।
डिक्शनरी पर for लूप
for लूप डिक्शनरी पर डिफ़ॉल्ट रूप से कुंजियों पर चलता है। कुंजी और मान एक साथ पाने के लिए items() पर चलाएँ — यह सबसे आम तरीका है।
spent = {"खाना": 650, "टैक्सी": 300}
for cat in spent: # कुंजियाँ
print(cat)
for amount in spent.values(): # मान
print(amount)
for cat, amount in spent.items(): # जोड़े
print(f"{cat}: {amount} ₹")
लूप चलते समय डिक्शनरी का आकार बदलना मना है — RuntimeError: dictionary changed size during iteration आएगा। कुछ कुंजियाँ हटानी हों, तो प्रतिलिपि पर चलें: for k in list(d):।
डिक्शनरी स्क्रीन पर दिखाना
print(d) डिक्शनरी को एक पंक्ति में छापता है। बड़ी या नेस्टेड डिक्शनरी के लिए मॉड्यूल pprint या json.dumps(d, ensure_ascii=False, indent=2) बेहतर है — वह डेटा को इंडेंट करके, बिना एस्केप वाले हिंदी अक्षरों के साथ दिखाता है।
डिक्शनरी की सॉर्टिंग
डिक्शनरी को उसी जगह सॉर्ट नहीं किया जा सकता — उसका sort मेथड नहीं है। सॉर्ट की गई डिक्शनरी का मतलब है sorted से निकले क्रमबद्ध जोड़ों से नई डिक्शनरी बनाना।
spent = {"टैक्सी": 300, "खाना": 650, "सिनेमा": 120}
by_key = dict(sorted(spent.items()))
print(by_key) # {'खाना': 650, 'टैक्सी': 300, 'सिनेमा': 120}
by_value = dict(sorted(spent.items(), key=lambda p: p[1], reverse=True))
print(by_value) # {'खाना': 650, 'टैक्सी': 300, 'सिनेमा': 120}
अगर सिर्फ़ टॉप-N श्रेणियाँ चाहिए, तो परिणाम को फिर से डिक्शनरी न बनाएँ: sorted(spent.items(), key=lambda p: p[1], reverse=True)[:2] जोड़ों की सूची लौटाएगा।
डिक्शनरी की सूची को किसी फ़ील्ड से सॉर्ट करने के लिए: sorted(users, key=lambda u: u["age"])।
डिक्शनरी मिलाना और जोड़ना
Python 3.9 से डिक्शनरी | ऑपरेटर से मिलती हैं, और |= उसी जगह अपडेट करता है। कुंजी मेल खाए तो दाहिने ऑपरेंड की जीत होती है।
a = {"x": 1, "y": 2}
b = {"y": 20, "z": 3}
print(a | b) # {'x': 1, 'y': 20, 'z': 3}
print({**a, **b}) # वही, अनपैकिंग से
a |= b # a.update(b) जैसा
ध्यान दें: डिक्शनरी के लिए a + b काम नहीं करता, TypeError आएगा। अगर सच में एक जैसी कुंजियों के मान जोड़ने हों, तो Counter लें: Counter(a) + Counter(b)।
डिक्शनरी की अनपैकिंग
दो तारे ** डिक्शनरी को फ़ंक्शन के नाम वाले आर्गुमेंट या किसी दूसरी डिक्शनरी में खोल देते हैं:
def greet(name, city):
return f"{name}, {city} से"
data = {"name": "अनीता", "city": "दिल्ली"}
print(greet(**data)) # अनीता, दिल्ली से
डिक्शनरी कॉम्प्रिहेंशन
डिक्शनरी कॉम्प्रिहेंशन किसी भी अनुक्रम से एक पंक्ति में डिक्शनरी बनाता है:
squares = {n: n * n for n in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
big = {k: v for k, v in spent.items() if v > 200}
inverted = {v: k for k, v in {"a": 1, "b": 2}.items()}
print(inverted) # {1: 'a', 2: 'b'}
आख़िरी उदाहरण डिक्शनरी को उलटने का तरीका है, जिसमें कुंजी और मान की जगह बदली जाती है। यह तब ठीक चलता है, जब मान अनूठे और हैश होने योग्य हों; वरना कुछ जोड़े खो जाएँगे।
नेस्टेड डिक्शनरी
मान खुद डिक्शनरी हो सकता है — इससे API के JSON जवाब या उपयोगकर्ताओं की «डिक्शनरी में डिक्शनरी» जैसी संरचनाएँ बनती हैं।
users = {
101: {"name": "अनीता", "skills": ["python", "sql"]},
102: {"name": "रवि", "skills": ["go"]},
}
print(users[101]["skills"][0]) # python
print(users.get(103, {}).get("name")) # None, KeyError के बिना
डिक्शनरी की कॉपी: प्रतिलिपि और दूसरा नाम
b = a डिक्शनरी की कॉपी नहीं बनाता, बल्कि उसी ऑब्जेक्ट पर दूसरा नाम दे देता है। b से बदलाव करेंगे, तो वह a में भी दिखेगा। फ़ंक्शन को डिक्शनरी देने पर भी यही होता है: फ़ंक्शन को साझा ऑब्जेक्ट मिलता है और वह उसे चुपचाप बिगाड़ सकता है।
import copy
a = {"limits": [0, 500]}
b = a.copy() # सतही प्रतिलिपि
b["limits"].append(1000) # भीतरी लिस्ट साझा है!
print(a) # {'limits': [0, 500, 1000]}
c = copy.deepcopy(a) # पूरी तरह स्वतंत्र प्रतिलिपि
डिक्शनरी की तुलना
== डिक्शनरी की विषय-वस्तु की तुलना करता है: सारे जोड़े मेल खाएँ तो बराबर। कुंजियों का क्रम इसमें नहीं गिना जाता: {"a": 1, "b": 2} == {"b": 2, "a": 1} True देता है। साझा कुंजियाँ खोजने के लिए व्यू पर सेट-ऑपरेशन लें: a.keys() & b.keys()।
टाइप वाली डिक्शनरी: एनोटेशन
डिक्शनरी का एनोटेशन dict[str, int] जैसा लिखा जाता है। अगर डिक्शनरी में अलग-अलग प्रकार के तय फ़ील्ड हों, तो typing मॉड्यूल का TypedDict सुविधाजनक है:
from typing import TypedDict
class User(TypedDict):
name: str
age: int
u: User = {"name": "अनीता", "age": 30}
एनोटेशन चलने के समय जाँचे नहीं जाते; उन्हें IDE और mypy जैसे विश्लेषक पढ़ते हैं।
न बदली जा सकने वाली डिक्शनरी: Python 3.15 का frozendict
Python 3.15 में बिल्ट-इन टाइप frozendict आया है (PEP 814): इसके लिए कोई इंपोर्ट नहीं चाहिए, और इसे बदलने की कोशिश तुरंत TypeError देती है। पहले न बदली जा सकने वाली डिक्शनरी के लिए types मॉड्यूल का रैपर या कोई बाहरी पैकेज लेना पड़ता था। साझा सेटिंग्स के लिए यही चाहिए, जिन्हें कोई फ़ंक्शन चुपचाप न बदल सके।
config = frozendict(min_amount=0, max_amount=500)
config["max_amount"] = 1000
# TypeError: 'frozendict' object does not support item assignment
strict = config | {"max_amount": 300} # नया frozendict, मूल सुरक्षित
cache = {config: "मई की रिपोर्ट"} # हैश होता है — कुंजी बन सकता है
कोर्स सामग्री के अनुसार ये बातें जानना ज़रूरी है:
frozendictobjectसे विरासत में मिलता है,dictसे नहीं; इसलिएisinstance(cfg, dict)Falseदेगा। «कोई भी डिक्शनरी» जाँचने के लिएcollections.abc.Mappingयाisinstance(x, (dict, frozendict))लें।- यह तभी हैश होता है जब उसकी कुंजियाँ और मान हैश होने योग्य हों:
frozendict(a=[1])बन जाता है, परhash()गिरेगा। न बदले जा सकने की गारंटी सतही है, टपल की तरह। - क्रम बचा रहता है, पर
==उसे नहीं गिनता। json.dumps,pickleऔरcopyfrozendict को समझते हैं।
आम गलतियाँ
- पढ़ते समय KeyError —
getयाinसे जाँच करें। - कुंजी के रूप में लिस्ट — उसे टपल बनाएँ:
d[tuple(lst)]। - लूप में डिक्शनरी बदलना —
list(d)पर चलें। - असाइनमेंट से कॉपी की उम्मीद —
copy()याdeepcopyकरें। {}को खाली सेट समझना — यह खाली डिक्शनरी है।
निष्कर्ष
Python की dict भाषा की मुख्य डेटा संरचना है: कुंजी से तेज़ खोज, डालने का क्रम बचा रहना, और get, setdefault, update जैसे मेथड, items() पर लूप, sorted से सॉर्टिंग और | से मिलाना। कॉपी और हैश होने योग्य कुंजियों का ध्यान रखें, और Python 3.15 में सेटिंग्स के लिए frozendict लें। डिक्शनरी, लिस्ट, टपल और सेट को «Python 3.15: शुरुआत से प्रो तक» कोर्स में ख़र्च ट्रैकर के उदाहरण पर व्यवहार में समझाया गया है।
अक्सर पूछे जाने वाले प्रश्न
क्या डिक्शनरी में अलग-अलग प्रकार के मान रखे जा सकते हैं?
हाँ, मान किसी भी प्रकार के हो सकते हैं और एक ही डिक्शनरी में अलग-अलग: संख्याएँ, स्ट्रिंग, लिस्ट, दूसरी डिक्शनरी। सीमा सिर्फ़ कुंजियों पर है — वे हैश होने योग्य होनी चाहिए।
डिक्शनरी में कुल कितने तत्व हैं, यह कैसे पता करें?
फ़ंक्शन len(d) जोड़ों (कुंजी — मान) की संख्या लौटाता है। खाली डिक्शनरी के लिए यह 0 होगा, और if की शर्त में खाली डिक्शनरी गलत मानी जाती है।
dict और defaultdict में क्या फ़र्क है?
defaultdict dict का उपवर्ग है, जो गायब कुंजी पर KeyError नहीं देता, बल्कि फ़ैक्टरी (जैसे int या list) से मान बना देता है। बाक़ी व्यवहार सामान्य डिक्शनरी जैसा ही है।
मान से कुंजी कैसे खोजें?
इसका सीधा मेथड नहीं है, लूप लगता है: next((k for k, v in d.items() if v == value), None)। अगर यह बार-बार करना हो, तो उलटी डिक्शनरी {v: k for k, v in d.items()} बना लें।
डिक्शनरी को फ़ाइल में कैसे सहेजें?
ज़्यादातर json मॉड्यूल से: लिखने के लिए खुली फ़ाइल में json.dump(d, f, ensure_ascii=False, indent=2), और पढ़ने के लिए json.load(f)। इसमें कुंजियाँ स्ट्रिंग बन जाती हैं।
यह विषय “Python 3.15: от новичка до профи” कोर्स में अभ्यास के साथ विस्तार से समझाया गया है।
कोर्स पर जाएँ