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

टपल्स और सेट्स

आप लिस्ट्स को जानते हैं। Python में दो और संग्रह प्रकार हैं जो उन समस्याओं को हल करते हैं जो लिस्ट्स नहीं कर सकतीं। टपल्स मानों का एक निश्चित समूह रखते हैं जो कभी नहीं बदलेगा। सेट्स केवल अद्वितीय मान रखते हैं और आपको तुरंत सदस्यता की जाँच करने देते हैं, चाहे संग्रह कितना भी बड़ा हो।

Python के संग्रह टूलकिट में चार प्रकार हैं। लिस्ट्स और डिक्ट्स अधिकांश सामान्य मामलों को संभालते हैं। टपल्स और सेट्स विशिष्ट मामलों को हल करते हैं: निश्चित रिकॉर्ड जहाँ अपरिवर्तनीयता एक संपत्ति है, और अद्वितीय-मान संग्रह जहाँ O(1) सदस्यता परीक्षण प्राथमिकता है।

list और dict से परे, Python tuple (अपरिवर्तनीय निश्चित-लंबाई अनुक्रम) और set (अद्वितीय हैश योग्य वस्तुओं का हैश-टेबल-समर्थित बिना क्रम वाला संग्रह) प्रदान करता है। प्रत्येक का एक विशिष्ट मेमोरी मॉडल, हैश योग्यता विशेषता और प्रदर्शन प्रोफ़ाइल है जिसे चुनने से पहले जानना उचित है।

टपल्स

टपल मानों का एक क्रमबद्ध समूह है जिसे बनाने के बाद बदला नहीं जा सकता। कोष्ठक टपल को परिभाषित करते हैं, लेकिन वे वैकल्पिक हैं। अल्पविराम ही वास्तव में इसे टपल बनाता है। एकल-आइटम टपल के लिए अंत में अल्पविराम आवश्यक है।

टपल्स अपरिवर्तनीय अनुक्रम हैं। अल्पविराम, कोष्ठक नहीं, टपल बनाता है। अपरिवर्तनीयता उन्हें हैश योग्य बनाती है जब उनके सभी तत्व भी हैश योग्य होते हैं, जो ऐसे उपयोग के मामले खोलती है जो लिस्ट्स नहीं भर सकतीं: डिक्ट कुंजी, सेट सदस्य, और निश्चित-संरचना रिकॉर्ड।

tuple एक अपरिवर्तनीय अनुक्रम है जो एक निश्चित-आकार C सरणी द्वारा समर्थित है। __hash__ तत्व हैश से गणना की जाती है जब सभी तत्व हैश योग्य होते हैं, जिससे टपल्स डिक्ट कुंजी और सेट सदस्यों के रूप में वैध हो जाते हैं। __getitem__ पूर्णांक और स्लाइस का समर्थन करता है; __setitem__ लागू नहीं है, इसलिए कोई भी म्यूटेशन प्रयास TypeError उठाता है। एकल-आइटम रूप (42,) के लिए अंत में अल्पविराम आवश्यक है; इसके बिना, कोष्ठक केवल समूहीकरण हैं।

python
point      = (10, 20)
rgb        = (255, 128, 0)
dimensions = (1920, 1080)
single     = (42,)            # एकल-आइटम टपल के लिए अंत में अल्पविराम आवश्यक
also_tuple = 42, 99           # कोष्ठक वैकल्पिक हैं; अल्पविराम इसे टपल बनाता है

इंडेक्स द्वारा एक्सेस बिल्कुल लिस्ट की तरह काम करता है। किसी आइटम को बदलने का प्रयास TypeError उठाता है:

इंडेक्सिंग, स्लाइसिंग और नकारात्मक इंडेक्स सभी लिस्ट्स की तरह समान रूप से काम करते हैं। इंडेक्स के माध्यम से असाइन करने का कोई भी प्रयास TypeError उठाता है; यह जानबूझकर है, सीमा नहीं।

पूर्णांकों और slice ऑब्जेक्ट्स के साथ __getitem__ list के समान क्लैम्पिंग नियमों का पालन करता है। कोई __setitem__ नहीं है: टपल प्रकार इसे रजिस्टर नहीं करता है, इसलिए TypeError रनटाइम पर उठाया जाता है, पार्स टाइम पर नहीं।

python
point = (10, 20)
point[0]    # 10
point[1]    # 20
point[-1]   # 20

point[0] = 99    # TypeError: 'tuple' object does not support item assignment

टपल का उपयोग कब करें

टपल का उपयोग तब करें जब आपके पास संबंधित मानों का एक छोटा समूह हो जो एक साथ हो और बदलेगा नहीं। निर्देशांक (x, y), एक रंग (r, g, b), एक नाम-स्कोर जोड़ी ("आरव", 87)। निश्चित संरचना कोड पढ़ने वाले किसी भी व्यक्ति को संकेत देती है कि इस समूह को एक इकाई के रूप में माना जाता है।

टपल्स निश्चित संरचना को संप्रेषित करते हैं: मानों का एक समूह जहाँ स्थिति का अर्थ होता है और समूह को एक इकाई के रूप में माना जाता है। उनकी हैश योग्यता उन्हें डिक्शनरी कुंजी के रूप में वैध बनाती है, जो लिस्ट्स नहीं हो सकतीं। टपल जो अनुबंध संकेत करता है वह है: ये मान एक साथ हैं और बदलने वाले नहीं हैं।

टपल्स निश्चित-आर्टी रिकॉर्ड के लिए मुहावरेदार प्रकार हैं। उनकी हैश योग्यता उन्हें कहीं भी उपयोग करने योग्य बनाती है जहाँ Hashable आवश्यक है: डिक्ट कुंजी, सेट सदस्य, functools.lru_cache कॉल हस्ताक्षर। शब्दार्थ अनुबंध एक लिस्ट से अलग है: टपल्स एक विषम रिकॉर्ड का प्रतिनिधित्व करते हैं जहाँ स्थिति का अर्थ होता है, लिस्ट्स एक समान अनुक्रम का प्रतिनिधित्व करती हैं जहाँ लंबाई और क्रम भिन्न हो सकते हैं।

python
locations = {}
locations[(40, -74)] = "New York"   # डिक्ट कुंजी के रूप में टपल, काम करता है
locations[[40, -74]] = "New York"   # डिक्ट कुंजी के रूप में लिस्ट, TypeError

अनपैकिंग

अनपैकिंग एक टपल से मानों को निकालती है और प्रत्येक को एक ही पंक्ति में अपने नाम पर असाइन करती है। नामों की संख्या मानों की संख्या से मेल खानी चाहिए। शेष आइटमों को एक लिस्ट में कैप्चर करने के लिए * का उपयोग करें।

अनपैकिंग किसी भी पुनरावृत्य पर काम करती है: टपल्स, लिस्ट्स, स्ट्रिंग्स। लक्ष्य नामों की गिनती पुनरावृत्य की लंबाई से मेल खानी चाहिए, जब तक कि एक तारांकित लक्ष्य चर-लंबाई स्लाइस को पकड़ न ले। बेमेल ValueError उठाता है। अनपैकिंग एक फ़ंक्शन से कई वापसी मानों का उपभोग करने का मुहावरेदार तरीका है।

अनपैकिंग दाईं ओर पर __iter__ कॉल करती है और प्रत्येक प्राप्त मान को संबंधित लक्ष्य नाम से बाँधती है। एक तारांकित लक्ष्य (*rest) शेष आइटमों को एक list में एकत्र करता है। बेमेल रनटाइम पर ValueError उठाता है। विस्तारित अनपैकिंग for हेडर के अंदर भी काम करती है: for x, y in list_of_pairs प्रत्येक पुनरावृत्ति आइटम को अनपैक करती है।

python
point = (10, 20)
x, y  = point

print(x)   # 10
print(y)   # 20

first, *rest = [1, 2, 3, 4, 5]
# first = 1, rest = [2, 3, 4, 5]

head, *middle, tail = [1, 2, 3, 4, 5]
# head = 1, middle = [2, 3, 4], tail = 5

नामित टपल्स

नामित टपल एक ऐसा टपल है जहाँ प्रत्येक स्थिति का एक नाम होता है। यह याद रखने के बजाय कि point[0] x-निर्देशांक है, आप point.x लिखते हैं। मान अभी भी अपरिवर्तनीय हैं; आपको बस संख्यात्मक स्थितियों के बजाय पठनीय विशेषता नाम मिलते हैं।

namedtuple एक वर्ग उत्पन्न करता है जो बिल्कुल टपल की तरह व्यवहार करता है लेकिन नामित विशेषता एक्सेस जोड़ता है। यह एक पूर्ण वर्ग से हल्का, अपरिवर्तनीय और स्व-दस्तावेजीकरण है। इसका उपयोग तब करें जब एक सादे टपल की स्थिति-आधारित एक्सेस को समझने के लिए एक टिप्पणी की आवश्यकता हो।

collections.namedtuple एक वर्ग फ़ैक्टरी है: यह रनटाइम पर नामित विशेषता एक्सेस संकलित करके एक tuple उपवर्ग उत्पन्न करता है। उत्पन्न वर्ग में _asdict(), _replace(), और _fields शामिल हैं। मेमोरी फुटप्रिंट एक सादे टपल के समान है। अधिक नियंत्रण के लिए (डिफ़ॉल्ट मान, प्रकार एनोटेशन, वैकल्पिक परिवर्तनशीलता), dataclasses.dataclass आधुनिक विकल्प है; प्रकार-एनोटेटेड टपल्स के लिए, typing.NamedTuple मुहावरेदार है।

Named tuple import

namedtuple Python की मानक लाइब्रेरी में है लेकिन इसे आयात करने की आवश्यकता है। from collections import namedtuple पंक्ति इस कोर्स में पहला आयात है। आयात Modules अध्याय में पूरी तरह से शामिल हैं।

python
from collections import namedtuple

Point  = namedtuple("Point",  ["x", "y"])
Player = namedtuple("Player", ["name", "score", "level"])

p = Point(10, 20)
p.x    # 10
p.y    # 20

alice = Player("आरव", 87, 5)
alice.name    # "आरव"
alice.score   # 87

सेट्स

सेट अद्वितीय मानों का एक संग्रह है जिसका कोई गारंटीकृत क्रम नहीं होता। एक ही मान को दो बार जोड़ना कुछ नहीं करता: एक सेट प्रत्येक आइटम की केवल एक प्रति रखता है। आइटम वाले सेट के लिए घुंघराले ब्रैकेट का उपयोग करें, या एक खाली सेट बनाने के लिए set() का उपयोग करें।

set एक बिना क्रम वाला संग्रह है जो स्वचालित रूप से डुप्लिकेट को अस्वीकार करता है। सदस्यता परीक्षण आकार की परवाह किए बिना O(1) है, जो इसे सही उपकरण बनाता है जब भी आपको यह जाँचने की आवश्यकता हो कि कोई मान एक बड़े संग्रह में मौजूद है या नहीं। नोट: {} एक खाली डिक्ट बनाता है, खाली सेट नहीं; उसके लिए set() का उपयोग करें।

set अद्वितीय हैश योग्य वस्तुओं का एक हैश-टेबल-समर्थित संग्रह है। सदस्यता परीक्षण, सम्मिलन, और हटाना सभी औसत O(1) हैं। पुनरावृत्ति क्रम आंतरिक हैश स्थितियों को दर्शाता है और रनों के बीच स्थिर नहीं है। केवल हैश योग्य वस्तुएँ सदस्य हो सकती हैं: int, str, tuple हाँ; list, dict, set नहीं। {} को एक खाली डिक्ट लिटरल के रूप में पार्स किया जाता है, सेट के रूप में नहीं।

python
tags     = {"python", "beginner", "tutorial"}
numbers  = {1, 2, 3, 4, 5}
empty    = set()    # {} नहीं (वह एक खाली डिक्ट है)

एक ही मान को दो बार जोड़ने से सेट नहीं बदलता:

python
tags.add("python")   # tags अपरिवर्तित है, "python" पहले से ही इसमें है

सेट का उपयोग कब करें

सेट्स तीन चीज़ों के लिए सही उपकरण हैं: एक लिस्ट से डुप्लिकेट हटाना, यह जल्दी से जाँचना कि कुछ एक बड़े संग्रह में है या नहीं, और दो समूहों की तुलना करना यह देखने के लिए कि वे क्या साझा करते हैं या किसमें भिन्न हैं।

सेट उपयोग को तीन अलग-अलग उपयोग मामले संचालित करते हैं: डुप्लिकेशन हटाना (सम्मिलन पर स्वचालित), O(1) सदस्यता परीक्षण (बनाम list के लिए O(n)), और सेट बीजगणित (|, &, -, ^)। जब संग्रह बड़ा होता है और आप बार-बार सदस्यता जाँचते हैं, तो प्रदर्शन का अंतर पर्याप्त होता है।

तीन विहित सेट उपयोग मामले सीधे हैश-टेबल गुणों पर मैप होते हैं: विशिष्टता (सम्मिलन पर डुप्लिकेट अस्वीकृति), O(1) औसत __contains__ (हैश लुकअप), और सेट बीजगणित (बिटवाइज़-शैली ऑपरेटर जो डंडर विधियों को कॉल करते हैं)। O(1) सदस्यता परीक्षण व्यावहारिक रूप से सबसे महत्वपूर्ण है: 10,000 आइटम वाले सेट पर in 10 के सेट पर जितना तेज़ है।

python
# एक लिस्ट से डुप्लिकेट हटाएँ
raw    = ["cat", "dog", "cat", "bird", "dog", "cat"]
unique = list(set(raw))   # ["cat", "dog", "bird"] (क्रम की गारंटी नहीं)
python
# तेज़ सदस्यता जाँच
valid_codes = {"USD", "EUR", "GBP", "JPY"}
code        = "EUR"

if code in valid_codes:    # तत्काल लुकअप, हज़ारों कोड के साथ भी
    print("Valid")

सेट संचालन

सेट्स वही संचालन समर्थित करते हैं जो आपने गणित में सीखे: यूनियन (किसी भी सेट में सब कुछ), इंटरसेक्शन (केवल वही जो दोनों सेट साझा करते हैं), और डिफ़रेंस (जो एक में है लेकिन दूसरे में नहीं)। Python इनके लिए ऑपरेटर प्रतीकों का उपयोग करता है, और प्रत्येक का एक विधि समकक्ष है।

Python के सेट ऑपरेटर गणितीय संकेतन को दर्शाते हैं: यूनियन के लिए |, इंटरसेक्शन के लिए &, डिफ़रेंस के लिए -, सिमेट्रिक डिफ़रेंस के लिए ^। प्रत्येक ऑपरेटर का एक विधि रूप है (.union(), .intersection(), आदि) जो किसी भी पुनरावृत्य को स्वीकार करता है, केवल सेट्स को नहीं।

सेट ऑपरेटर डंडर विधियों को कॉल करते हैं: | __or__ को कॉल करता है, & __and__ को कॉल करता है, - __sub__ को कॉल करता है, ^ __xor__ को कॉल करता है। ऑपरेटरों को दोनों ऑपरेंड को सेट होने की आवश्यकता होती है और अन्यथा TypeError उठाते हैं। विधि रूप किसी भी पुनरावृत्य को स्वीकार करते हैं और इसे आंतरिक रूप से परिवर्तित करते हैं। इन-प्लेस रूप (|=, &=, -=, ^=) बाएँ ऑपरेंड को संशोधित करते हैं, .update(), .intersection_update(), आदि के बराबर।

python
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

a | b    # {1, 2, 3, 4, 5, 6}   (यूनियन: किसी भी में सब कुछ)
a & b    # {3, 4}               (इंटरसेक्शन: केवल दोनों में)
a - b    # {1, 2}               (डिफ़रेंस: a में लेकिन b में नहीं)
b - a    # {5, 6}               (दूसरी तरह डिफ़रेंस)
a ^ b    # {1, 2, 5, 6}        (सिमेट्रिक डिफ़रेंस: एक में लेकिन दोनों में नहीं)

इनके विधि रूप भी हैं: .union(), .intersection(), .difference(), .symmetric_difference()

सेट्स को संशोधित करना

सेट्स परिवर्तनशील हैं। .add() एक आइटम जोड़ता है। .update() किसी भी लिस्ट या अन्य पुनरावृत्य से एक बार में कई जोड़ता है। .remove() एक आइटम हटाता है लेकिन यदि वह वहाँ नहीं है तो त्रुटि उठाता है। .discard() आइटम मौजूद होने पर चुपचाप हटाता है और न होने पर कुछ नहीं करता।

.add() औसतन O(1) है। .update() किसी भी पुनरावृत्य को स्वीकार करता है और एक लूप में .add() कॉल करने के बराबर है। .remove() मिस पर KeyError उठाता है, dict.__delitem__ को दर्शाता है। .discard() सुरक्षित विकल्प है जब उपस्थिति अनिश्चित हो। .pop() एक मनमाना तत्व हटाता है, "अंतिम" नहीं क्योंकि सेट्स का कोई क्रम नहीं होता।

.add(x) x को हैश करता है और तालिका में सम्मिलित करता है: औसत O(1)। .update(iterable) |= के बराबर है। .remove() मिस पर KeyError उठाता है। .discard() पहले हैश लुकअप करता है और मिस पर हटाना छोड़ देता है। .pop() एक मनमाना तत्व हटाता है जो आंतरिक हैश तालिका स्थिति द्वारा निर्धारित होता है, सम्मिलन क्रम से नहीं।

python
tags = {"python", "beginner"}

tags.add("tutorial")          # एक आइटम जोड़ें
tags.update(["web", "api"])   # किसी भी पुनरावृत्य से कई आइटम जोड़ें
tags.remove("beginner")       # हटाएँ, न मिलने पर KeyError उठाता है
tags.discard("missing")       # हटाएँ, न मिलने पर कोई त्रुटि नहीं
tags.pop()                    # हटाएँ और एक मनमाना आइटम लौटाएँ
tags.clear()                  # सब कुछ हटा दें

जब आप सुनिश्चित न हों कि आइटम मौजूद है, तो .discard() का उपयोग करें।

फ्रोज़न सेट्स

फ्रोज़न सेट एक ऐसा सेट है जिसे आप बनाने के बाद संशोधित नहीं कर सकते। एक का उपयोग करने का मुख्य कारण: फ्रोज़न सेट्स हैश योग्य हैं, इसलिए उन्हें डिक्शनरी कुंजी के रूप में उपयोग किया जा सकता है या अन्य सेट्स के अंदर संग्रहीत किया जा सकता है।

frozenset set का अपरिवर्तनीय समकक्ष है। यह सभी पठन संचालन और सेट बीजगणित का समर्थन करता है लेकिन म्यूटेशन का नहीं। इसकी अपरिवर्तनीयता इसे हैश योग्य बनाती है, जिसका अर्थ है कि यह एक डिक्ट कुंजी के रूप में या किसी अन्य सेट के अंदर एक सदस्य के रूप में वैध है।

frozenset __hash__ लागू करता है जो तत्व हैश के एक क्रमबद्ध रिडक्शन से गणना की जाती है, जिससे इसे एक स्थिर हैश मान मिलता है। नए संग्रह लौटाने वाले सभी सेट बीजगणित ऑपरेटर और विधियाँ समर्थित हैं; म्यूटेशन विधियाँ (add, remove, आदि) परिभाषित नहीं हैं। frozenset एक स्थिर लुकअप तालिका के लिए सही प्रकार है जो रनटाइम पर नहीं बदलनी चाहिए और जिसे डिक्ट कुंजी के रूप में उपयोग करने की आवश्यकता हो सकती है।

python
valid_statuses = frozenset({"active", "paused", "deleted"})
valid_statuses.add("archived")    # AttributeError, frozenset अपरिवर्तनीय है

सही संग्रह चुनना

चार प्रकार, प्रत्येक की एक स्पष्ट भूमिका है। पूछें कि आपको डेटा के साथ क्या करने की आवश्यकता है और सही विकल्प आमतौर पर स्पष्ट हो जाता है।

संग्रह प्रकारों के बीच चयन इस बारे में है कि कौन से संचालन मायने रखते हैं और आपके डेटा में क्या बाधाएँ हैं: परिवर्तनशीलता, क्रम, डुप्लिकेट हैंडलिंग, और लुकअप रणनीति।

संग्रह चयन एक प्रदर्शन और शब्दार्थ निर्णय है। dict और set हैशिंग के माध्यम से O(1) औसत लुकअप प्रदान करते हैं। list और tuple O(1) इंडेक्स्ड एक्सेस लेकिन O(n) सदस्यता परीक्षण प्रदान करते हैं। tuple की अपरिवर्तनीयता हैश योग्यता खरीदती है। frozenset और tuple मानक लाइब्रेरी में दो हैश योग्य संयुक्त प्रकार हैं।

listtuplesetdict
क्रमबद्धहाँहाँनहींहाँ (सम्मिलन क्रम)
परिवर्तनशीलहाँनहींहाँहाँ
डुप्लिकेटहाँहाँनहींनहीं (कुंजी)
एक्सेस द्वाराइंडेक्सइंडेक्सn/aकुंजी
उपयोग करें जबक्रमबद्ध, परिवर्तनीय अनुक्रमनिश्चित रिकॉर्डअद्वितीय मान, तेज़ सदस्यताकुंजी-मान लुकअप

एक त्वरित निर्णय नियम:

  • नाम से कुछ देखना है? → dict
  • एक क्रमबद्ध संग्रह की आवश्यकता है जिसे आप संशोधित करेंगे? → list
  • संबंधित मानों का एक निश्चित समूह है? → tuple
  • अद्वितीय मान या तेज़ सदस्यता परीक्षण की आवश्यकता है? → set

व्यवहार में

निश्चित रिकॉर्ड संग्रहीत करने के लिए टपल्स और अद्वितीय मानों को ट्रैक करने के लिए एक सेट का उपयोग करना:

python
home   = (28.6139, 77.2090)   # अक्षांश, देशांतर
office = (28.5355, 77.3910)

home_lat, home_lon = home
print(f"Home: {home_lat}, {home_lon}")

# एक सेट के साथ अद्वितीय आगंतुकों को ट्रैक करें
visitors = set()
visitors.add("आरव")
visitors.add("राहुल")
visitors.add("आरव")    # पहले से सेट में, चुपचाप अनदेखा किया गया
visitors.add("प्रिया")

print(f"Unique visitors: {len(visitors)}")
print(f"आरव visited: {'आरव' in visitors}")
print(f"विकास visited:  {'विकास' in visitors}")

जो पहले से संसाधित किया जा चुका है उसे ट्रैक करने और शेष कार्य की गणना करने के लिए सेट्स का उपयोग करना:

python
already_processed = {"report_jan.csv", "report_feb.csv"}
all_files         = {"report_jan.csv", "report_feb.csv", "report_mar.csv", "report_apr.csv"}

to_process = all_files - already_processed
print(f"Files to process: {sorted(to_process)}")

for filename in sorted(to_process):
    print(f"Processing {filename}...")
    already_processed.add(filename)

print(f"Done. Total processed: {len(already_processed)}")

स्थिर लुकअप तालिकाओं के लिए frozenset का उपयोग करना और सेट बीजगणित के साथ O(1) सदस्यता परीक्षण का प्रदर्शन करना:

python
ALLOWED_METHODS = frozenset({"GET", "POST", "PUT", "PATCH", "DELETE"})
SAFE_METHODS    = frozenset({"GET", "HEAD", "OPTIONS"})

# frozensets पर सेट बीजगणित एक नियमित सेट लौटाता है
unsafe_allowed = ALLOWED_METHODS - SAFE_METHODS
print(f"Non-safe allowed methods: {unsafe_allowed}")

# frozenset हैश योग्य है, इसलिए इसे एक सेट में संग्रहीत किया जा सकता है (एक सादा सेट नहीं हो सकता)
method_groups = {
    frozenset({"GET", "HEAD", "OPTIONS"}),
    frozenset({"POST", "PUT", "PATCH"}),
    frozenset({"DELETE"}),
}
print(f"Method groups: {len(method_groups)}")

method = "POST"
print(f"Allowed: {method in ALLOWED_METHODS}")
print(f"Safe:    {method in SAFE_METHODS}")

frozenset O(1) लुकअप प्रदान करता है और इसे कहीं भी संग्रहीत किया जा सकता है जहाँ एक हैश योग्य प्रकार आवश्यक हो। दो frozenset ऑब्जेक्ट्स पर सेट बीजगणित एक सादा set लौटाता है; इसे अपरिवर्तनीय रखने के लिए परिणाम को frozenset() में लपेटें।