लैम्ब्डा और कॉम्प्रिहेंशन
इन तीनों फ़ीचर्स में एक बात समान है: ये आपको ऐसे विचार व्यक्त करने देते हैं जिनके लिए अन्यथा कई पंक्तियाँ लगतीं, एक ही पठनीय एक्सप्रेशन में। अच्छे से उपयोग करने पर, ये कोड को छोटा और स्पष्ट बनाते हैं। गलत तरीके से उपयोग करने पर, ये उसे अपठनीय बना देते हैं। यह अध्याय बताता है कि प्रत्येक का उपयोग कब करें और कब रुकें।
लैम्ब्डा फ़ंक्शन
लैम्ब्डा एक नामहीन, एक-एक्सप्रेशन वाला फ़ंक्शन है। आप इसे lambda कीवर्ड से बनाते हैं। इसकी असली उपयोगिता यह है कि आप इसे इनलाइन लिख सकते हैं, ठीक वहीं जहाँ आपको ज़रूरत हो, बिना पहले नामित फ़ंक्शन परिभाषित किए। यही बात इसे sorted() के साथ उपयोगी बनाती है।
double = lambda x: x * 2
double(5) # 10यह इसके समतुल्य है:
def double(x):
return x * 2ज़्यादातर मामलों के लिए, def का उपयोग करें। लैम्ब्डा का एक वास्तविक फ़ायदा है: आप उन्हें इनलाइन लिख सकते हैं, ठीक वहीं जहाँ आपको ज़रूरत हो, बिना नाम दिए। यही बात उन्हें sorted(), map(), और filter() के साथ उपयोगी बनाती है:
players = [("आर्या", 87), ("रोहन", 74), ("कविता", 92)]
sorted(players, key=lambda p: p[1]) # स्कोर के अनुसार क्रमबद्ध करें (आरोही)
sorted(players, key=lambda p: p[1], reverse=True) # स्कोर के अनुसार क्रमबद्ध करें (अवरोही)लैम्ब्डा के बिना, आपको केवल key= आर्ग्युमेंट के लिए एक नामित फ़ंक्शन परिभाषित करना पड़ता। लैम्ब्डा इरादे को स्थानीय और दृश्यमान रखता है।
लैम्ब्डा कई आर्ग्युमेंट्स ले सकते हैं:
add = lambda a, b: a + b
add(3, 4) # 7लैम्ब्डा का उपयोग कब करें: केवल तब जब यह एक सरल एक्सप्रेशन हो जो एक ही जगह उपयोग किया जाता है। यदि यह जटिल हो रहा है, या आपको इसे पुन: उपयोग करना है, तो उचित def लिखें। एक लैम्ब्डा जो कई ऑपरेटरों में फैला हो या जिसमें कंडीशनल्स की आवश्यकता हो, आमतौर पर def पर स्विच करने का संकेत है।
लिस्ट कॉम्प्रिहेंशन
Python में सबसे आम परिवर्तन: एक सीक्वेंस लें, हर आइटम के साथ कुछ करें, और एक नई लिस्ट प्राप्त करें। एक लिस्ट कॉम्प्रिहेंशन यह एक पठनीय पंक्ति में करता है: [expression for item in iterable]। आप if के साथ एक फ़िल्टर भी जोड़ सकते हैं।
लंबा तरीका:
numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
squares.append(n ** 2)लिस्ट कॉम्प्रिहेंशन:
squares = [n ** 2 for n in numbers]संरचना हमेशा एक जैसी होती है: [expression for item in iterable]।
scores = [87, 42, 96, 55, 71]
scaled = [s * 1.1 for s in scores] # 10% बोनस लागू करें
as_grades = [f"{s}/100" for s in scores] # प्रत्येक को प्रारूपित करेंएक शर्त के साथ फ़िल्टरिंग
केवल उन आइटम्स को शामिल करने के लिए एक if क्लॉज़ जोड़ें जो परीक्षण पास करते हैं। परिणाम एक नई लिस्ट है जिसमें केवल वे आइटम होते हैं जहाँ शर्त True है।
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
evens = [n for n in numbers if n % 2 == 0] # [2, 4, 6, 8]
odds = [n for n in numbers if n % 2 != 0] # [1, 3, 5, 7]scores = [87, 42, 96, 55, 71, 38]
passing = [s for s in scores if s >= 60] # [87, 96, 71]
failing = [s for s in scores if s < 60] # [42, 55, 38]नेस्टेड कॉम्प्रिहेंशन
आप लिस्ट्स की लिस्ट को एक एकल लिस्ट में समतल करने के लिए कॉम्प्रिहेंशन को नेस्ट कर सकते हैं। इसे बाएँ से दाएँ पढ़ें: प्रत्येक पंक्ति के लिए, उस पंक्ति के प्रत्येक आइटम के लिए, आइटम को शामिल करें।
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [item for row in matrix for item in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]इसे बाएँ से दाएँ पढ़ें: matrix की प्रत्येक row के लिए, row के प्रत्येक item के लिए, item को शामिल करें।
नेस्टेड कॉम्प्रिहेंशन जल्दी भ्रामक हो सकते हैं। यदि इसे पार्स करने में एक क्षण से अधिक समय लगता है, तो लूप्स को स्पष्ट रूप से लिखें।
डिक्ट कॉम्प्रिहेंशन
डिक्ट कॉम्प्रिहेंशन एक एक्सप्रेशन में एक डिक्शनरी बनाते हैं, लिस्ट कॉम्प्रिहेंशन के समान विचार का उपयोग करते हुए: {key: value for item in iterable}। लिस्ट कॉम्प्रिहेंशन की तरह ही if के साथ एक फ़िल्टर जोड़ें।
names = ["आर्या", "रोहन", "कविता"]
scores = [87, 74, 92]
score_map = {name: score for name, score in zip(names, scores)}
# {"आर्या": 87, "रोहन": 74, "कविता": 92}एक फ़िल्टर के साथ:
passing = {name: score for name, score in score_map.items() if score >= 80}
# {"आर्या": 87, "कविता": 92}words = ["apple", "banana", "cherry"]
word_lens = {word: len(word) for word in words}
# {"apple": 5, "banana": 6, "cherry": 6}सेट कॉम्प्रिहेंशन
सेट कॉम्प्रिहेंशन एक एक्सप्रेशन में एक सेट बनाते हैं, कर्ली ब्रेसेस के साथ और बिना कोलन के। चूँकि परिणाम एक सेट है, डुप्लिकेट्स स्वचालित रूप से हटा दिए जाते हैं।
words = ["apple", "banana", "cherry", "apple"]
unique = {w.lower() for w in words} # {"apple", "banana", "cherry"}सेट कॉम्प्रिहेंशन का उपयोग तब करें जब आप अद्वितीय मान चाहते हैं और क्रम की परवाह नहीं करते।
जनरेटर एक्सप्रेशन
जनरेटर लिस्ट कॉम्प्रिहेंशन की तरह दिखते हैं, ब्रैकेट्स के बजाय कोष्ठक के साथ। मुख्य अंतर: एक लिस्ट कॉम्प्रिहेंशन पूरी लिस्ट को एक बार में मेमोरी में बनाता है। एक जनरेटर एक समय में एक मान उत्पन्न करता है, केवल जब आवश्यक हो। बड़े सीक्वेंस के लिए, यह बहुत कम मेमोरी का उपयोग करता है।
squares_gen = (n ** 2 for n in range(1000000))total = sum(n ** 2 for n in range(1000000)) # sum() जनरेटर का उपभोग करता हैजब sum(), max(), min(), या any() जैसे फ़ंक्शन को सीधे एक जनरेटर पास करते हैं, तो आप अतिरिक्त कोष्ठक छोड़ सकते हैं:
total = sum(n ** 2 for n in range(1000)) # कोष्ठक का एक सेट, दो नहींअधिकांश रोज़मर्रा के कोड के लिए, लिस्ट कॉम्प्रिहेंशन ठीक हैं। जनरेटर का उपयोग तब करें जब आप बड़े डेटासेट या स्ट्रीमिंग डेटा को संसाधित कर रहे हों जहाँ सब कुछ मेमोरी में रखना बेकार होगा।
zip()
zip() दो या अधिक सीक्वेंस के आइटम्स को एक साथ जोड़ता है ताकि आप उन्हें समानांतर में लूप कर सकें। यह सबसे छोटे सीक्वेंस पर रुक जाता है। जब दो लिस्ट एक-दूसरे के अनुरूप हों, तो इंडेक्स प्रबंधित करने से बचने का यह स्वच्छ तरीका है।
names = ["आर्या", "रोहन", "कविता"]
scores = [87, 74, 92]
for name, score in zip(names, scores):
print(f"{name}: {score}")
# आर्या: 87
# रोहन: 74
# कविता: 92zip() सबसे छोटे सीक्वेंस पर रुक जाता है। यदि आपके सीक्वेंस अलग-अलग लंबाई के हो सकते हैं, तो एक फिल वैल्यू के साथ itertools.zip_longest() का उपयोग करें।
ज़िप्ड जोड़ों की लिस्ट से वापस दो अलग-अलग लिस्ट में बदलने के लिए, zip(*pairs) का उपयोग करें:
pairs = [("आर्या", 87), ("रोहन", 74), ("कविता", 92)]
names, scores = zip(*pairs)
# names = ("आर्या", "रोहन", "कविता")
# scores = (87, 74, 92)यहाँ * क्या करता है?
*pairs लिस्ट को अलग आर्ग्युमेंट्स में अनपैक करता है: zip(*pairs) बन जाता है zip(("आर्या", 87), ("रोहन", 74), ("कविता", 92))। * ऑपरेटर Functions अध्याय में कवर किया गया है।
zip() मैन्युअल रूप से इंडेक्स प्रबंधित किए बिना समानांतर में कई सीक्वेंस को इटरेट करने का स्वच्छ तरीका भी है:
before = [10, 20, 30]
after = [15, 18, 35]
for b, a in zip(before, after):
change = a - b
print(f"{b} -> {a} ({'+' if change >= 0 else ''}{change})")map() और filter()
map() और filter() पुराने फ़ंक्शनल-स्टाइल टूल्स हैं जो वही करते हैं जो कॉम्प्रिहेंशन करते हैं। आप उन्हें पुराने कोड में देखेंगे, इसलिए यह जानना सार्थक है कि उनका क्या मतलब है। नए कोड के लिए कॉम्प्रिहेंशन को प्राथमिकता दें; वे अधिकांश Python डेवलपर्स के लिए अधिक पठनीय हैं।
numbers = [1, 2, 3, 4, 5]
list(map(lambda x: x ** 2, numbers)) # [1, 4, 9, 16, 25]
list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]कॉम्प्रिहेंशन को प्राथमिकता दें; वे अधिकांश Python डेवलपर्स के लिए अधिक पठनीय हैं। map() का उपयोग तब करें जब आपके पास एक नामित फ़ंक्शन हो जो पहले से मौजूद है:
strings = ["1", "2", "3"]
numbers = list(map(int, strings)) # [1, 2, 3] (यहाँ कॉम्प्रिहेंशन से अधिक स्वच्छ)व्यवहार में
एक प्लेयर लिस्ट को पासिंग स्कोर तक फ़िल्टर करें, sorted और एक लैम्ब्डा के साथ स्कोर के अनुसार रैंक करें, फिर गणना की गई स्थितियों के साथ प्रिंट करें:
players = [
{"name": "आर्या", "score": 87},
{"name": "रोहन", "score": 42},
{"name": "कविता", "score": 96},
{"name": "विकास", "score": 55},
]
passing = [p for p in players if p["score"] >= 60]
ranked = sorted(passing, key=lambda p: p["score"], reverse=True)
score_map = {p["name"]: p["score"] for p in ranked}
for i, (name, score) in enumerate(score_map.items(), start=1):
print(f"{i}. {name}: {score}")
