Skip to content
This page has been auto-translated and may contain errors.View in English

डिक्शनरीज़

लिस्ट्स आपको चीज़ों को स्थिति (position) से ढूँढने देती हैं। लेकिन अक्सर आप किसी चीज़ को नाम से ढूँढना चाहते हैं। "मुझे आइटम 3 दो" नहीं, बल्कि "मुझे आरव का स्कोर दो"। एक डिक्शनरी डेटा को key-value जोड़ों के रूप में स्टोर करती है: आप एक value को उसकी key से ढूँढते हैं, न कि उसकी स्थिति से।

जब किसी लिस्ट का स्थानीय (positional) इंडेक्स अर्थपूर्ण नहीं होता, तो डिक्शनरी सही संरचना है। Dicts मनमानी keys को values के साथ मैप करती हैं, जिससे आपको O(1) समय में नामित (named) लुकअप मिलता है। एक लीडरबोर्ड, एक JSON रिस्पॉन्स, एक कॉन्फ़िग फ़ाइल: सभी को स्वाभाविक रूप से key-value मैपिंग के रूप में व्यक्त किया जाता है।

dict एक हैश-टेबल-समर्थित key-value स्टोर है जिसमें औसत O(1) लुकअप, इंसर्शन और डिलीशन होता है। Keys हैश-योग्य (hashable) होनी चाहिए; values कोई भी ऑब्जेक्ट हो सकती हैं। Python 3.7 से, dicts इंसर्शन ऑर्डर को संरक्षित रखते हैं। dict Python नेमस्पेसेज़, ऑब्जेक्ट __dict__ एट्रिब्यूट्स और कीवर्ड आर्ग्युमेंट्स की नींव है।

एक डिक्शनरी बनाना

प्रत्येक key और value के बीच एक कोलन के साथ कर्ली ब्रेसेस, और जोड़ों के बीच कॉमा। Keys लगभग हमेशा स्ट्रिंग्स होती हैं। Values कुछ भी हो सकती हैं: नंबर, स्ट्रिंग्स, अन्य लिस्ट्स, यहाँ तक कि अन्य डिक्शनरीज़ भी।

Dict लिटरल्स key: value सिंटैक्स के साथ कर्ली ब्रेसेस का उपयोग करते हैं। Keys कोई भी अपरिवर्तनीय (हैश-योग्य) प्रकार हो सकती हैं: स्ट्रिंग्स, इंटीजर्स, ट्यूपल्स। Values कोई भी Python ऑब्जेक्ट हो सकती हैं। Dicts इंसर्शन ऑर्डर को संरक्षित रखते हैं, इसलिए जब आप इटरेट करते हैं, तो आइटम उसी क्रम में मिलते हैं जिस क्रम में उन्हें जोड़ा गया था।

Dict लिटरल्स का मूल्यांकन बाएँ से दाएँ किया जाता है। Keys हैश-योग्य होनी चाहिए: str, int, tuple काम करते हैं; list और dict नहीं। Values पर कोई प्रतिबंध नहीं है। Python 3.7 के अनुसार इंसर्शन ऑर्डर की गारंटी है (3.6 से कॉम्पैक्ट हैश टेबल के रूप में लागू किया गया)। किसी लिटरल में डुप्लिकेट keys चुपचाप अंतिम value का उपयोग करती हैं।

python
player = {
    "name":  "आरव",
    "score": 87,
    "level": 5,
    "alive": True,
}

Values तक पहुँचना

Value प्राप्त करने के लिए key के साथ स्क्वायर ब्रैकेट्स का उपयोग करें। यदि key मौजूद नहीं है, तो Python KeyError उठाता है। .get() का उपयोग करें जब आपको यकीन न हो कि key वहाँ है: यह क्रैश होने के बजाय None लौटाता है, या आपके द्वारा निर्दिष्ट डिफ़ॉल्ट value।

स्क्वायर ब्रैकेट एक्सेस एक गायब key पर KeyError उठाता है। .get(key) मिस पर None लौटाता है। .get(key, default) इसके बजाय डिफ़ॉल्ट लौटाता है। जब भी key की उपस्थिति अनिश्चित हो तो .get() का उपयोग करें; यह try/except में एक्सेस को लपेटने की तुलना में सुरक्षित और अधिक पठनीय है।

d[key] __getitem__ को कॉल करता है, जो key को हैश करता है और टेबल को प्रोब करता है: औसत O(1)। मिस पर यह KeyError उठाता है। .get(key, default=None) वही प्रोब करता है लेकिन मिस पर उठाने के बजाय डिफ़ॉल्ट लौटाता है। key in d चेक (जो __contains__ को कॉल करता है) O(1) है और एक्सेस से पहले रक्षा करने का मुहावरेदार तरीका है।

python
player = {"name": "आरव", "score": 87}

player["name"]    # "आरव"
player["score"]   # 87
player["lives"]   # KeyError (key doesn't exist)
python
player.get("score")          # 87
player.get("lives")          # None (no error, returns None by default)
player.get("lives", 3)       # 3   (use this default if key is absent)

.get() तब सुरक्षित होता है जब कोई key गायब हो सकती है:

python
count = inventory.get("arrows", 0)   # 0 if "arrows" isn't in the dict

जोड़ना और अपडेट करना

स्क्वायर ब्रैकेट्स के साथ एक key को असाइन करें। यदि key पहले से मौजूद है, तो value बदल दी जाती है। यदि यह अभी तक मौजूद नहीं है, तो एक नई एंट्री बनाई जाती है। पूरी अन्य डिक्शनरी को एक बार में मर्ज करने के लिए .update() का उपयोग करें।

किसी key को असाइनमेंट __setitem__ को कॉल करता है: औसत O(1), बनाता या बदलता है। .update() एक अन्य dict या key-value जोड़ों का एक इटरेबल स्वीकार करता है और प्रत्येक एंट्री के लिए __setitem__ को कॉल करता है, मौजूदा keys को ओवरराइट करता है।

d[key] = value __setitem__ को कॉल करता है, जो key को हैश करता है और टेबल में इंसर्ट या ओवरराइट करता है: औसत O(1)। .update(other) बार-बार __setitem__ कॉल्स के बराबर है। | ऑपरेटर (Python 3.9+) म्यूटेशन के बिना dicts को मर्ज करता है और एक नया dict लौटाता है; |= जगह में म्यूटेट करता है।

python
player = {"name": "आरव", "score": 87}

player["score"] = 92        # update existing
player["level"] = 5         # add new key
python
extras = {"level": 5, "alive": True}
player.update(extras)   # adds/overwrites with keys from extras

आइटम्स हटाना

एंट्रीज़ हटाने के चार तरीके। .pop() एक key को हटाता है और आपको value वापस देता है। .pop() एक डिफ़ॉल्ट के साथ तब सुरक्षित है जब key वहाँ नहीं हो सकती। del बिना रिटर्न value के एक key को हटाता है। .clear() पूरी डिक्शनरी को खाली कर देता है।

.pop(key) मिस पर KeyError उठाता है। .pop(key, default) इसके बजाय डिफ़ॉल्ट लौटाता है, जिससे यह सुरक्षित हटाने की मेथड बन जाती है। del d[key] __delitem__ को कॉल करता है और मिस पर KeyError उठाता है। .clear() सभी एंट्रीज़ को हटा देता है लेकिन dict ऑब्जेक्ट को स्वयं रखता है।

.pop(key, default) एक एकल हैश प्रोब है: औसत O(1)। del d[key] __delitem__ को कॉल करता है, वही प्रोब, मिस पर उठाता है। हटाने के बाद, मेमोरी मुक्त करने के लिए हैश टेबल सिकुड़ सकती है। .clear() टेबल आकार को रीसेट करता है। एक dict को इटरेट करना और उसी लूप में उसे म्यूटेट करना RuntimeError उठाता है; पहले हटाने के लिए keys की एक लिस्ट बनाएँ।

python
player = {"name": "आरव", "score": 87, "level": 5}

player.pop("level")            # removes "level" and returns 5
player.pop("lives", None)      # safe pop, returns None if key absent
del player["score"]            # removes "score", no return value
player.clear()                 # removes everything

.pop() एक डिफ़ॉल्ट के साथ उस key को हटाने का सबसे सुरक्षित तरीका है जो शायद मौजूद न हो।

इटरेट करना

तीन व्यू आपको एक डिक्शनरी के विभिन्न हिस्सों के माध्यम से लूप करने देते हैं। केवल dict को इटरेट करने से आपको keys मिलती हैं। .values() values देता है। .items() दोनों एक साथ देता है और यही आप सबसे ज़्यादा उपयोग करेंगे: प्रत्येक जोड़ी को साफ़, पठनीय लूप्स के लिए दो नामों में अनपैक करें।

.keys(), .values(), और .items() view objects लौटाते हैं, लिस्ट्स नहीं। व्यूज़ dict की वर्तमान स्थिति को गतिशील रूप से दर्शाते हैं: यदि आप dict को संशोधित करते हैं, तो व्यू तुरंत अपडेट हो जाता है। .items() अधिकांश लूप्स के लिए सबसे उपयोगी है क्योंकि ट्यूपल अनपैकिंग for k, v in d.items() स्पष्ट रूप से पढ़ी जाती है।

.keys(), .values(), और .items() dict_keys, dict_values, और dict_items व्यू ऑब्जेक्ट्स लौटाते हैं। व्यूज़ आलसी (lazy) हैं: वे डेटा कॉपी नहीं करते और जब अंतर्निहित dict बदलता है तो अपडेट होते हैं। dict_keys सेट बीजगणित (&, |, -) का समर्थन करता है क्योंकि keys अद्वितीय और हैश-योग्य होती हैं। इटरेशन के दौरान dict को म्यूटेट करना RuntimeError उठाता है; यदि आवश्यक हो तो स्नैपशॉट के लिए list(d.items()) का उपयोग करें।

python
player = {"name": "आरव", "score": 87, "level": 5}

for key in player:               # iterate keys (most common)
    print(key)

for key in player.keys():        # same, explicit keys view
    print(key)

for value in player.values():    # just the values
    print(value)

for key, value in player.items():   # both, most useful
    print(f"{key}: {value}")

.items() यही आप सबसे ज़्यादा उपयोग करेंगे। प्रत्येक जोड़ी को दो नामों में अनपैक करना लूप को पठनीय बनाता है।

सदस्यता जाँचना

in जाँचता है कि क्या एक key डिक्शनरी में मौजूद है। यह values को नहीं जाँचता, केवल keys को। यह जाँचने के लिए कि कोई चीज़ मौजूद नहीं है, not in का उपयोग करें।

in और not in __contains__ को कॉल करते हैं, जो dicts के लिए O(1) है। यह केवल keys की जाँच करता है। Values जाँचने के लिए, आप in d.values() का उपयोग करेंगे, लेकिन यह O(n) है क्योंकि values इंडेक्स नहीं की जातीं।

key in d dict.__contains__ को कॉल करता है, जो key को हैश करता है और टेबल को प्रोब करता है: औसत O(1)। value in d.values() values व्यू को इटरेट करता है: O(n)। यह असमानता values को स्कैन करने पर लुकअप के लिए dict keys को प्राथमिकता देने का एक मुख्य कारण है।

python
player = {"name": "आरव", "score": 87}

"name"  in player      # True
"lives" in player      # False
"lives" not in player  # True

in केवल keys की जाँच करता है। Values जाँचने के लिए, in player.values() का उपयोग करें, हालाँकि यह शायद ही कभी आवश्यक होता है।

नेस्टेड डिक्शनरीज़

Values स्वयं डिक्शनरीज़ हो सकती हैं। इसी तरह आप कई स्तरों के साथ संरचित डेटा का प्रतिनिधित्व करते हैं: एक खिलाड़ी जिसका एक स्टैट्स सेक्शन है, उप-सेक्शन्स के साथ एक कॉन्फ़िग फ़ाइल। स्क्वायर ब्रैकेट्स के दो सेट एक नेस्टेड value तक पहुँचते हैं: पहला बाहरी key चुनता है, दूसरा आंतरिक key चुनता है।

नेस्टेड dicts ऐसे dicts हैं जहाँ values स्वयं dicts हैं। चेन किए गए सबस्क्रिप्ट्स के साथ एक्सेस करें। एक आंतरिक dict को म्यूटेट करना बाहरी dict को प्रभावित करता है क्योंकि बाहरी dict उसी ऑब्जेक्ट का संदर्भ रखता है। जहाँ संभव हो नेस्टिंग को उथला रखें: गहरी नेस्टिंग जल्दी ही पढ़ने और नेविगेट करने में कठिन हो जाती है।

नेस्टेड dicts ऑब्जेक्ट संदर्भों को स्टोर करते हैं, कॉपीज़ को नहीं। बाहरी dict की उथली कॉपी (d.copy()) आंतरिक dicts की कॉपी नहीं करती; आंतरिक dicts में म्यूटेशन्स मूल और कॉपी दोनों के माध्यम से दिखाई देते हैं। गहरी नेस्टेड संरचनाओं के लिए, copy.deepcopy() पूरी तरह से स्वतंत्र कॉपीज़ बनाता है। चेन किए गए __getitem__ कॉल्स में से प्रत्येक O(1) है, इसलिए एक्सेस गहराई की कोई एसिम्प्टोटिक लागत नहीं है।

python
users = {
    "आरव": {"score": 87, "level": 5},
    "रिया": {"score": 74, "level": 3},
}

users["आरव"]["score"]   # 87
users["रिया"]["level"]   # 3

चेन किए गए स्क्वायर ब्रैकेट्स के साथ एक्सेस करें। गहरी नेस्टेड संरचनाओं के लिए, यह बोझिल हो सकता है, इसलिए जहाँ आप कर सकते हैं, नेस्टिंग को उथला रखें।

setdefault

.setdefault() एक key को पढ़ता है यदि वह मौजूद है, या यदि वह नहीं है तो उसे एक डिफ़ॉल्ट value पर सेट करता है, फिर value लौटाता है। यह तब उपयोगी होता है जब आपको एक key के मौजूद होने की आवश्यकता हो लेकिन यदि वह पहले से वहाँ है तो उसे ओवरराइट नहीं करना चाहते।

.setdefault(key, default) एक एटॉमिक read-or-create है: यदि key मौजूद है, बिना कुछ बदले उसकी वर्तमान value लौटाओ; यदि नहीं है, तो डिफ़ॉल्ट डालो और उसे लौटाओ। सामान्य उपयोग केस अलग अस्तित्व जाँच के बिना समूहीकृत संरचनाओं का निर्माण करना है।

.setdefault(key, default) एक एकल हैश प्रोब है: औसत O(1)। यदि key अनुपस्थित है, default डाला जाता है और लौटाया जाता है। यदि मौजूद है, मौजूदा value लौटाई जाती है और default अनदेखा कर दिया जाता है (जाँच के बाद कभी मूल्यांकित नहीं)। सामान्य "आइटम्स को लिस्ट्स में समूहीकृत करें" पैटर्न के लिए, यह एपेंड करने से पहले key in d की जाँच करने का मानक विकल्प है।

python
inventory = {}

inventory.setdefault("arrows", 0)    # sets "arrows": 0, returns 0
inventory.setdefault("arrows", 10)   # "arrows" already exists, no change, returns 0

यह पहले key के अस्तित्व की जाँच किए बिना समूहीकृत संरचनाओं के निर्माण के लिए उपयोगी है:

python
groups = {}

for name, team in players:
    groups.setdefault(team, []).append(name)

collections.defaultdict और Counter

मानक लाइब्रेरी में दो dict उपवर्ग (subclasses) हैं जो सामान्य पैटर्न्स को स्वचालित रूप से संभालते हैं। defaultdict गायब keys के लिए एक डिफ़ॉल्ट value बनाता है ताकि आपको कभी KeyError न मिले। Counter गिनता है कि प्रत्येक आइटम किसी अनुक्रम में कितनी बार दिखाई देता है और परिणाम आपको एक dict के रूप में देता है।

defaultdict एक कॉल करने योग्य (callable) लेता है जो नई keys के लिए डिफ़ॉल्ट value उत्पन्न करता है, .setdefault() की आवश्यकता को समाप्त करता है। Counter फ़्रीक्वेंसी काउंटिंग के लिए एक विशेष dict है जिसमें एक .most_common() मेथड है। दोनों dict उपवर्ग हैं, इसलिए सभी मानक dict ऑपरेशन्स उन पर काम करते हैं।

defaultdict.__missing__ फ़ैक्टरी को कॉल करता है और परिणाम को स्टोर करता है, जो इसे सामान्य केस के लिए थ्रेड-सुरक्षित बनाता है। Counter dict को उपवर्गित करता है और .most_common(n) (heapq के माध्यम से O(n log n)), .subtract(), और काउंट्स को संयोजित करने के लिए अंकगणितीय ऑपरेटर्स जोड़ता है। दोनों collections में हैं; इम्पोर्ट्स Modules अध्याय में कवर किए गए हैं।

collections import

defaultdict और Counter को मानक लाइब्रेरी से इम्पोर्ट करने की आवश्यकता है। इम्पोर्ट्स Modules अध्याय में कवर किए गए हैं।

python
from collections import defaultdict

groups = defaultdict(list)
for name, team in players:
    groups[team].append(name)   # no KeyError if team is new
python
from collections import Counter

words  = ["cat", "dog", "cat", "bird", "cat", "dog"]
counts = Counter(words)
# Counter({'cat': 3, 'dog': 2, 'bird': 1})

counts.most_common(2)   # [('cat', 3), ('dog', 2)]

Counter बहुत सारे "एक लूप में चीज़ें गिनने" वाले बॉयलरप्लेट को बचाता है।

व्यवहार में

एक स्कोर ट्रैकर बनाना और सभी एंट्रीज़ के साथ एक सारांश प्रिंट करना:

python
scores = {"आरव": 87, "रिया": 74, "नेहा": 92, "विवेक": 55}

total   = sum(scores.values())
average = total / len(scores)

print(f"Players:  {len(scores)}")
print(f"Average:  {average:.1f}")
print(f"Highest:  {max(scores.values())}")
print(f"Lowest:   {min(scores.values())}")
print()

for name, score in scores.items():
    print(f"  {name}: {score}")

एक लूप में प्रति-फ़ाइल परिणामों का एक dict बनाना, फिर सभी एंट्रीज़ में सारांशित करना:

python
job_results = {}
files       = ["report_jan.csv", "report_feb.csv", "report_mar.csv"]

for filename in files:
    size = len(filename) * 100   # placeholder for real file size
    if size < 2000:
        status = "ok"
    else:
        status = "large"
    job_results[filename] = {"size": size, "status": status}

ok_count    = 0
large_count = 0

for result in job_results.values():
    if result["status"] == "ok":
        ok_count += 1
    else:
        large_count += 1

print(f"Processed {len(job_results)} file(s): {ok_count} ok, {large_count} large")

आवश्यक फ़ील्ड्स को इटरेट करके एक नेस्टेड रिक्वेस्ट dict को मान्य करना, फिर एक फ़ीचर महत्व dict को जगह में सामान्यीकृत करना:

python
request = {
    "method":  "POST",
    "path":    "/users",
    "headers": {"Content-Type": "application/json"},
    "body":    {"username": "आरव", "email": "[email protected]"},
}

body   = request["body"]
errors = []

for field in ["username", "email"]:
    if not body.get(field):
        errors.append(f"Missing required field: {field}")

if "email" in body and "@" not in body["email"]:
    errors.append("Invalid email format")

print(f"Method: {request['method']} {request['path']}")
if errors:
    print(f"Errors: {errors}")
else:
    print("Validation passed")

# Normalise feature importance values to sum to 1
feature_importance = {"age": 0.34, "income": 0.28, "region": 0.15, "purchases": 0.23}
total = sum(feature_importance.values())

for key in feature_importance:
    feature_importance[key] = round(feature_importance[key] / total, 3)

print(f"Normalised: {feature_importance}")