कॉम्प्रिहेंशन — एक पंक्ति में लूप
लिस्ट, डिक्शनरी और सेट कॉम्प्रिहेंशन, फ़िल्टर करने वाले if और चुनने वाले if/else का अंतर, और कब कॉम्प्रिहेंशन लिखना गलत चुनाव है।
- 1समस्या
- 2समझें
- 3उदाहरण
- 4अनुमान
- 5स्वयं करें
- 6चुनौती
वह समस्या जिसे हम हल कर रहे हैं
कोड का एक पैटर्न पिछले छह अध्यायों में बार-बार सामने आया है:
marks = [72, 45, 90, 33]
doubled = []
for mark in marks:
doubled.append(mark * 2)
print(doubled)
doubled = [mark * 2 for mark in marks]
print(doubled)[144, 90, 180, 66]
[144, 90, 180, 66]ऊपर की चार पंक्तियाँ और नीचे की एक पंक्ति बिल्कुल वही काम करती हैं।
उन चार में से तीन पंक्तियाँ वास्तविक काम नहीं हैं, वे केवल व्यवस्था संबंधी हैं — एक खाली सूची बनाएं, स्रोत पर लूप चलाएं, हर बार append करें। एकमात्र वास्तविक निर्णय mark * 2 है। बाकी सब कुछ हर बार एक जैसा होता है।
एक कॉम्प्रिहेंशन (Comprehension) उस दोहराव को हटा देता है। यह कोई नई क्षमता नहीं है — यह वही है जो आप पहले से लिख सकते थे, कम शब्दों में।
इस मिशन के अंत तक आप सीखेंगे
- लिस्ट कॉम्प्रिहेंशन लिखना और पढ़ना
ifके साथ फ़िल्टर करना, औरif/elseके साथ चुनना- डिक्शनरी और सेट कॉम्प्रिहेंशन लिखना
- यह बताना कि कब कॉम्प्रिहेंशन का उपयोग करना गलत विकल्प है
- एक अपठनीय कॉम्प्रिहेंशन को वापस सामान्य लूप में बदलना
पूर्वापेक्षाएँ: नेस्टेड डेटा — डिक्शनरी की लिस्ट.
संरचना
[ मुझे क्या चाहिए for प्रत्येक वस्तु in यह कहाँ से आता है ]इसे ज़ोर से पढ़ने पर यह एक साधारण वाक्य है: "`marks` में प्रत्येक `mark` के लिए `mark 2`"*.
इसे समझने का एक तरीका: पहले for भाग को पढ़ें, फिर शुरुआत को।
फ़िल्टर करना (Filtering)
अंत में एक if केवल उन चीज़ों को रखता है जो शर्त से मेल खाती हैं:
marks = [72, 45, 90, 33]
passed = [mark for mark in marks if mark >= 40]
print(passed)[72, 45, 90]फ़िल्टरिंग और ट्रांसफ़ॉर्मिंग एक साथ किए जा सकते हैं:
names = [" rafi ", "AHMED", " dia"]
clean = [name.strip().lower() for name in names if name.strip()]
print(clean)['rafi', 'ahmed', 'dia']शर्त name.strip() बिना किसी तुलना के है। याद रखें: खाली टेक्स्ट falsy होता है। इसलिए केवल रिक्त स्थान (spaces) टाइप करने वाले को हटा दिया जाता है।
अंत में if बनाम शुरुआत में if
दो अलग-अलग चीज़ें हैं, और स्थिति ही पूरा अंतर है:
marks = [72, 33, 90]
labels = ["pass" if m >= 40 else "fail" for m in marks]
print(labels)['pass', 'fail', 'pass']अंत में if फ़िल्टर करता है — कुछ चीज़ें परिणाम तक कभी नहीं पहुँचतीं, इसलिए परिणाम छोटा हो सकता है।
शुरुआत में if ... else चुनता है — प्रत्येक वस्तु कुछ न कुछ उत्पन्न करती है, इसलिए लंबाई अपरिवर्तित रहती है।
क्या परिणाम की लंबाई बदलती है? यह सवाल दोनों को अलग करने का सबसे आसान तरीका है।
डिक्शनरी और सेट भी
वही संरचना, अलग कोष्ठक:
marks = {"rafi": 72, "ahmed": 45, "bilal": 90}
passed = {name: mark for name, mark in marks.items() if mark >= 50}
print(passed)
doubled = {name: mark * 2 for name, mark in marks.items()}
print(doubled){'rafi': 72, 'bilal': 90}
{'rafi': 144, 'ahmed': 90, 'bilal': 180}मँझले कोष्ठक और एक कोलन एक डिक्शनरी कॉम्प्रिहेंशन बनाते हैं।
बिना कोलन के वही मँझले कोष्ठक एक सेट बनाते हैं:
orders = [
{"item": "pen"},
{"item": "bag"},
{"item": "pen"},
]
items = {order["item"] for order in orders}
print(sorted(items))['bag', 'pen']अध्याय 16 का "कितने अलग-अलग" प्रश्न एक ही पंक्ति में। pen दो बार आता है और एक बार दिखाई देता है।
संख्याओं को टेक्स्ट में बदलना
यह पंक्ति अध्याय 13 में आई थी:
marks = [72, 45, 90]
print(", ".join(str(m) for m in marks))
print([str(m) for m in marks])72, 45, 90
['72', '45', '90']str(m) for m in marks बिना चौकोर कोष्ठक के एक कॉम्प्रिहेंशन है — इस रूप को जनरेटर एक्सप्रेशन (generator expression) कहा जाता है।
इसे कब नहीं लिखना चाहिए
कॉम्प्रिहेंशन लिखने में सक्षम होने का मतलब यह नहीं है कि आपको हमेशा लिखना ही चाहिए। इसे देखें:
rows = [["1", "2"], ["3", "x"]]
numbers = [int(c) for row in rows for c in row if c.isdigit()]
print(numbers)[1, 2, 3]पंक्ति सही है। लेकिन इसमें दो for और एक if हैं। छह महीने बाद उस पंक्ति को पढ़ना मुश्किल होगा।
लूप के रूप में:
rows = [["1", "2"], ["3", "x"]]
numbers = []
for row in rows:
for c in row:
if c.isdigit():
numbers.append(int(c))
print(numbers)[1, 2, 3]अधिक पंक्तियाँ, लेकिन स्पष्ट सोच। कोड का लक्ष्य छोटा होना नहीं बल्कि स्पष्ट होना है।
एक व्यावहारिक नियम: एक for और अधिकतम एक if — कॉम्प्रिहेंशन। उससे अधिक — एक लूप। और कभी भी कॉम्प्रिहेंशन के अंदर print या append न रखें।
एक संपूर्ण उदाहरण
views.py:
# रिकॉर्ड्स की एक सूची, तीन अलग-अलग दृश्य (views)
orders = [
{"customer": "rafi", "item": "pen", "quantity": 3, "price": 15.0},
{"customer": "ahmed", "item": "bag", "quantity": 1, "price": 850.0},
{"customer": "rafi", "item": "ink", "quantity": 2, "price": 120.0},
{"customer": "dia", "item": "pen", "quantity": 5, "price": 15.0},
]
totals = [order["quantity"] * order["price"] for order in orders]
print("Totals :", totals)
big = [order["item"] for order in orders if order["quantity"] * order["price"] > 100]
print("Over 100 :", big)
items = {order["item"] for order in orders}
print("Distinct :", sorted(items))
by_item = {order["item"]: order["price"] for order in orders}
print("Price list:", by_item)
print("Grand :", sum(totals))Totals : [45.0, 850.0, 240.0, 75.0]
Over 100 : ['bag', 'ink']
Distinct : ['bag', 'ink', 'pen']
Price list: {'pen': 15.0, 'bag': 850.0, 'ink': 120.0}
Grand : 1210.0जब यह टूटता है
अंत में if और else रखने से SyntaxError [m for m in marks if m >= 40 else 0] मान्य नहीं है। फ़िल्टरिंग if अंत में जाता है और इसमें कोई else नहीं होता; चयन करने वाला if ... else आगे जाता है: [m if m >= 40 else 0 for m in marks].
परिणाम None से भरा है कॉम्प्रिहेंशन के अंदर कुछ ऐसा लिखा है जो कुछ नहीं लौटाता — जैसे [items.append(x) for x in other]। append कुछ नहीं लौटाता (None), इसलिए परिणाम None की एक सूची बन जाता है।
NameError — कॉम्प्रिहेंशन का वेरिएबल उसके बाहर नहीं मिलता [m * 2 for m in marks] के बाद आप m का उपयोग नहीं कर सकते।
चरण 4 / 6 — अनुमान
अपनी समझ की जाँच करें
There is an if at the end. What is printed?
marks = [72, 45, 90, 33]
passed = [mark for mark in marks if mark >= 40]
print(passed)- A[72, 45, 90]
- B[72, 45, 90, 33]
- C[True, True, True, False]
- D[33]
This time the if is at the front, with an else. What is printed?
marks = [72, 33, 90]
labels = ["pass" if m >= 40 else "fail" for m in marks]
print(labels)- A['pass', 'fail', 'pass']
- B['pass', 'pass']
- C[72, 90]
- D['pass', 'fail']
append is called inside a comprehension. What do the two lines print?
source = ["pen", "bag"]
target = []
result = [target.append(item) for item in source]
print(target)
print(result)- A['pen', 'bag'] [None, None]
- B['pen', 'bag'] ['pen', 'bag']
- C[] ['pen', 'bag']
- DA `TypeError`
उत्तर देने के लिए अकाउंट आवश्यक है
अपने उत्तर जाँचने के लिए साइन इन करें
प्रश्न ऊपर दिए गए हैं, और मन में उत्तर सोचना ही मुख्य कार्य है। सही उत्तर, व्याख्या और तीन-स्तरीय संकेत देखने के लिए साइन इन करें।
आपकी बारी
अव्यवस्थित नामों की एक सूची वाली clean.py नामक फ़ाइल लिखें — कुछ अतिरिक्त रिक्त स्थान के साथ, कुछ बड़े अक्षरों में, और कम से कम एक जो पूरी तरह से खाली हो।
कॉम्प्रिहेंशन का उपयोग करके बनाएं:
- साफ़ नामों की एक सूची — अतिरिक्त स्पेस हटाए गए, लोअरकेस में, खाली नाम हटाए गए
- प्रत्येक नाम की लंबाई की एक सूची
- पाँच वर्णों से अधिक लंबे नामों की एक सूची
{name: length}की एक डिक्शनरी- पहले अक्षरों का एक सेट
फिर दो प्रयोग:
- नंबर 1 को फिर से एक साधारण
forलूप के रूप में लिखें, और जाँचें कि दोनों परिणाम==के साथ बराबर हैं। - दो
forऔर एकifके साथ एक कॉम्प्रिहेंशन लिखें, फिर इसे एक लूप में अलग करें। कौन सा पढ़ना आसान है?
Step 6 of 6
चुनौती — the chapter quiz
सरल से कठिन — दस प्रश्न, अंतिम वाले जानबूझकर चुनौतीपूर्ण बनाए गए हैं।
Sign in to take the quiz