अध्याय 14

टपल और अनपैकिंग

एक ऐसी लिस्ट जिसे बदला नहीं जा सकता — कहाँ इसकी ज़रूरत है, अनपैकिंग से इंडेक्स के बजाय नामों का उपयोग, एक लाइन में अदला-बदली, और (5) बनाम (5,) का जाल।

30 मिनटPython 3.12
  1. 1समस्या
  2. 2समझें
  3. 3उदाहरण
  4. 4अनुमान
  5. 5स्वयं करें
  6. 6चुनौती

वह समस्या जिसे हम हल कर रहे हैं

तीन दिनों के मौसम का रिकॉर्ड रखना है — प्रत्येक दिन के लिए नाम, तापमान और आर्द्रता (humidity)।

एक लिस्ट यह काम कर सकती है: ["monday", 31.5, 78]। यह काम करता है, लेकिन दो बातें परेशान करती हैं।

पहला, उस सूची को बदला जा सकता है। यदि कोई गलती से सोमवार के रिकॉर्ड में कुछ append कर देता है, तो पायथन कुछ नहीं कहेगा — भले ही एक रिकॉर्ड में कभी भी चार चीज़ें नहीं होनी चाहिए थीं। किसी ऐसी चीज़ को जो बदलनी नहीं चाहिए, एक ऐसे कंटेनर में रखना जिसे बदला जा सकता है, एक शांत जोखिम है।

दूसरा, तीनों मानों को वापस प्राप्त करने का अर्थ है record[0], record[1], record[2] लिखना — संख्या द्वारा, नाम से नहीं। छह महीने बाद, record[1] को पढ़ने वाला कोई भी व्यक्ति यह नहीं जान पाएगा कि यह तापमान है या आर्द्रता।

एक टपल (Tuple) दोनों का उत्तर देता है: यह एक ऐसी लिस्ट है जिसे बदला नहीं जा सकता — और यह अनपैकिंग (unpacking) नामक एक क्षमता लाता है, जो आपको इंडेक्स के बजाय नामों का उपयोग करने देता है।

इस मिशन के अंत तक आप सीखेंगे

  • एक टपल बनाना, और यह बताना कि कहाँ टपल सही है और कहाँ लिस्ट सही नहीं है
  • अनपैकिंग के साथ एक साथ कई नामों में कई मान रखना
  • एक ही पंक्ति में दो चरों (variables) की अदला-बदली करना
  • (5) और (5,) के बीच अंतर समझना
  • यह समझाना कि टपल पर append कॉल करने पर AttributeError क्यों आता है

पूर्वापेक्षाएँ: लिस्ट सॉर्ट करना और उसके मेथड्स.


टपल — एक ऐसी लिस्ट जिसे बदला नहीं जा सकता

चौकोर कोष्ठक के बजाय गोल कोष्ठक ():

python
point = (3, 7)

print(point)
print(point[0])
print(len(point))
text
(3, 7)
3
2

पढ़ना, इंडेक्सिंग, len, स्लाइसिंग, in, for के साथ चलना — जो कुछ भी आपने लिस्ट के साथ किया वह यहाँ काम करता है। केवल एक बड़ा अंतर है:

python
point = (3, 7)
point[0] = 5
text
TypeError: 'tuple' object does not support item assignment

क्या यह संदेश जाना-पहचाना लगता है? यह शब्द-दर-शब्द वही है जो अध्याय 6 ने तब दिया था जब टेक्स्ट के अंदर किसी अक्षर को बदला गया था, 'str' के स्थान पर 'tuple' के साथ। पायथन की सभी अपरिवर्तनीय चीज़ें एक ही भाषा में शिकायत करती हैं।

बदलने वाले मेथड भी अनुपस्थित हैं:

python
point = (3, 7)
point.append(9)
text
AttributeError: 'tuple' object has no attribute 'append'

AttributeError का अर्थ है "इस प्रकार की वस्तु में ऐसा कोई मेथड नहीं है"। एक टपल को बदला नहीं जा सकता, इसलिए इसमें वे मेथड ही नहीं होते जो चीज़ों को बदलते हैं।

यह एक लाभ क्यों है, सीमा नहीं

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

निर्देशांक (coordinate) (3, 7) में तीसरी संख्या जोड़ने का कोई मतलब नहीं है। एक तिथि (2026, 9, 16) का कोई चौथा भाग नहीं होता। टपल में रखे जाने पर, वे गलतियाँ बाद में बग बनने के बजाय तुरंत त्रुटि (error) के रूप में सामने आ जाती हैं।

एक नियम के रूप में: चीज़ों की एक निश्चित संख्या, जिनमें से प्रत्येक का एक अलग अर्थ हो — टपल। अज्ञात संख्या में चीज़ें, जो सभी एक ही प्रकार की हों — लिस्ट।

इसलिए तीन दिनों का मौसम एक लिस्ट के अंदर टपल है: दिनों की संख्या अज्ञात है और बढ़ सकती है (एक लिस्ट), लेकिन प्रत्येक रिकॉर्ड में ठीक तीन चीज़ें होती हैं (एक टपल)।

अनपैकिंग (Unpacking) — जहाँ असली लाभ है

python
point = (3, 7)
x, y = point

print(x)
print(y)
text
3
7

एक ही पंक्ति में दो नाम और दो मान। और अब यह point[1] के बजाय y है — एक ऐसा नाम जो पढ़ने पर स्वयं स्पष्ट होता है।

बाईं ओर उतने ही नाम होने चाहिए जितने दाईं ओर मान हैं:

python
point = (3, 7)
x, y, z = point
text
ValueError: not enough values to unpack (expected 3, got 2)

अनपैकिंग केवल टपल तक सीमित नहीं है; यह लिस्ट पर भी काम करती है। यह टपल के साथ सबसे उपयोगी है क्योंकि वहाँ मानों की संख्या पहले से ज्ञात होती है।

एक ही पंक्ति में अदला-बदली

अन्य भाषाओं को दो मानों का आदान-प्रदान करने के लिए एक अस्थायी तीसरे चर की आवश्यकता होती है। पायथन को नहीं:

python
a = 1
b = 2

a, b = b, a
print(a, b)
text
2 1

पंक्ति कैसे काम करती है यह समझने योग्य है: पायथन पहले पूरे दाहिने हिस्से का मूल्यांकन करता है, एक टपल (2, 1) बनाता है, और फिर उसे बाईं ओर अनपैक करता है। इसलिए यद्यपि a बदलता है, b का पुराना मान पहले ही सुरक्षित कर लिया गया है, और कुछ भी नहीं खोता है।

कोष्ठक वास्तव में अनिवार्य नहीं हैं

python
point = 3, 7
print(point)
print(type(point))
text
(3, 7)
<class 'tuple'>

जो चीज़ टपल बनाती है वह अल्पविराम (comma) है, कोष्ठक नहीं। कोष्ठक पठनीयता के लिए हैं। एक बार जब आप यह जान जाते हैं, तो a, b = b, a जादू जैसा दिखना बंद हो जाता है — दाईं ओर b, a केवल एक टपल है।

और इसी से एक जाल निकलता है:

python
one = (5)
really = (5,)

print(type(one))
print(type(really))
print(len(really))
text
<class 'int'>
<class 'tuple'>
1

(5) कोई टपल नहीं है — यह कोष्ठक में एक संख्या है, बिल्कुल (2 + 3) की तरह। एक मान का टपल बनाने के लिए अल्पविराम की आवश्यकता होती है: (5,)। यह एक टाइपो जैसा दिखता है, लेकिन वह अल्पविराम ही पूरा अंतर है।

लूप में टपल

python
people = [("rafi", 22), ("ahmed", 35)]

for name, age in people:
    print(f"{name} is {age}")
text
rafi is 22
ahmed is 35

for name, age in people प्रत्येक टपल को सीधे दो नामों में अनपैक करता है।

आपने इसे बिना जाने पहले ही इस्तेमाल किया है: enumerate टपल वापस लौटाता है। पिछले अध्याय में for position, item in enumerate(...) लिखना वास्तव में उन्हें अनपैक करना ही था।

दोनों के बीच रूपांतरण

python
as_list = [3, 7]
as_tuple = (3, 7)

as_list.append(9)
print(as_list)
print(as_tuple)
print(list(as_tuple))
print(tuple(as_list))
text
[3, 7, 9]
(3, 7)
[3, 7]
(3, 7, 9)

list() और tuple() एक से दूसरा बनाते हैं — हर बार एक नई चीज़, मूल को अछूता छोड़ते हुए।


एक संपूर्ण उदाहरण

weather.py:

python
# एक ऐसा रिकॉर्ड जिसे बदला नहीं जाना चाहिए, उसके लिए टपल सही संरचना है
readings = [
    ("monday", 31.5, 78),
    ("tuesday", 33.0, 71),
    ("wednesday", 29.5, 85),
]

print("Day        Temp   Humidity")
for day, temp, humidity in readings:
    print(f"{day:<10} {temp:>5}  {humidity:>5}")

hottest = readings[0]
for reading in readings:
    if reading[1] > hottest[1]:
        hottest = reading

day, temp, humidity = hottest
print()
print(f"Hottest was {day} at {temp}")

temps = []
for _, temp, _ in readings:
    temps.append(temp)

print("Temps      :", temps)
print("Average    :", round(sum(temps) / len(temps), 2))
text
Day        Temp   Humidity
monday      31.5     78
tuesday     33.0     71
wednesday   29.5     85

Hottest was tuesday at 33.0
Temps      : [31.5, 33.0, 29.5]
Average    : 31.33

चार बातें ध्यान देने योग्य हैं:

बाहर एक सूची, अंदर टपल। दिनों की संख्या बढ़ सकती है, इसलिए बाहरी चीज़ एक सूची है। प्रत्येक रिकॉर्ड में ठीक तीन चीज़ें होती हैं, इसलिए आंतरिक चीज़ें टपल हैं।

f"{day:<10}" और f"{temp:>5}" कॉलमों को संरेखित रखते हैं। < बाएं संरेखित करता है, > दाएं संरेखित करता है।

for _, temp, _ in readings — अंडरस्कोर (_) एक प्रथागत नाम है जिसका अर्थ है "मुझे इसकी आवश्यकता नहीं है"।


जब यह टूटता है

TypeError: 'tuple' object does not support item assignment टपल के अंदर किसी मान को बदलने का प्रयास। टपल को बदला नहीं जा सकता — या तो शुरू से ही एक सूची का उपयोग करें, या list(...) से बदलें, संशोधित करें और वापस टपल बनाएं।

AttributeError: 'tuple' object has no attribute 'append' टपल पर कोई भी संशोधन मेथड — append, remove, sort — मौजूद नहीं होता।

ValueError: not enough values to unpack (expected 3, got 2) दाईं ओर के मानों की तुलना में बाईं ओर अधिक नाम हैं।

मैंने एक मान का टपल बनाया और यह टपल नहीं है अल्पविराम छूट गया है। (5) एक संख्या है; (5,) एक टपल है।