लैम्डा और कम्प्रिहेंशन

इन तीनों फीचर्स में कुछ समान है: वे आपको ऐसे विचार व्यक्त करने देते हैं जो अन्यथा कई लाइनें लेते हैं एक साथ, एक पठनीय एक्सप्रेशन में। सही तरीके से उपयोग किए जाने पर, वे कोड को छोटा और स्पष्ट करते हैं। गलत तरीके से उपयोग किए जाने पर, वे इसे अपठनीय बनाते हैं। यह चैप्टर कवर करता है कि कब हर एक के लिए पहुंचें और कब रुकें।
लैम्डा फंक्शन
एक लैम्डा एक अनाम, एक-एक्सप्रेशन फ़ंक्शन है। आप इसे 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 पर स्विच करने का संकेत है।
lambda कीवर्ड के साथ लिखा गया है। इसका पूरा अस्तित्व का कारण `sorted()` के लिए key= के रूप में इनलाइन जाना है ताकि आप एक अलग फंक्शन को एक काम के लिए परिभाषित न करें। जिस क्षण यह एक साफ एक्सप्रेशन से लंबा हो जाता है, मैं एक असली `def` लिखता हूं और इसे लेकर बेहतर महसूस करता हूं। सूची कम्प्रिहेंशन
पायथन में सबसे सामान्य ट्रांसफॉर्मेशन: एक सीक्वेंस लें, हर आइटम पर कुछ करें, एक नई सूची वापस पाएं। एक सूची कम्प्रिहेंशन यह एक पठनीय लाइन में करता है: [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] # हर एक को फॉर्मेट करें[expression for item in iterable] एक सीक्वेंस लेता है, हर आइटम पर एक काम करता है, और आपको एक नई सूची वापस देता है। इसे बाएं से दाएं पढ़ें और यह बिल्कुल कहता है कि यह क्या करता है। यह पहली पायथन फीचर थी जिसने मुझे महसूस कराया कि मैं पायथन लिख रहा हूं दूसरी भाषा से अनुवाद करने के बजाय। एक शर्त के साथ फ़िल्टर करना
केवल आइटम शामिल करने के लिए एक 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]if condition जोड़ें जो परीक्षा पास करते हैं: [x for x in data if x > 0]। कुछ भी जो गलत आता है नई सूची से बाहर रहता है। समान कम्प्रिहेंशन जो आप पहले से जानते हैं, इसके साथ एक दरवाजा व्यक्ति है। नेस्टेड कम्प्रिहेंशन
आइटम की एक सूची को एक एकल सूची में समतल करने के लिए आप कम्प्रिहेंशन को नेस्ट कर सकते हैं। इसे बाएं से दाएं पढ़ें: हर पंक्ति के लिए, उस पंक्ति में हर आइटम के लिए, आइटम को शामिल करें।
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]इसे बाएं से दाएं पढ़ें: मैट्रिक्स में हर पंक्ति के लिए, पंक्ति में हर आइटम के लिए, आइटम को शामिल करें।
नेस्टेड कम्प्रिहेंशन जल्दी भ्रमित करने वाली हो सकते हैं। अगर इसे पार्स करने में एक पल से अधिक समय लगता है, लूप को स्पष्ट रूप से लिखें।
for क्लॉज एक सूची सूची को एक एकल सपाट सूची में समतल करते हैं: [item for row in matrix for item in row]। इसे बाएं से दाएं, बाहरी लूप पहले पढ़ें, बिल्कुल वैसी ही क्रम में जैसे आप लूप लिखेंगे। अगर आपकी आंखें इस पर अटक जाती हैं, यह असली लूप लिखने का संकेत है। डिक्ट कम्प्रिहेंशन
डिक्ट कम्प्रिहेंशन एक डिक्शनरी को एक एक्सप्रेशन में बनाते हैं, सूची कम्प्रिहेंशन के समान विचार का उपयोग करते हुए: {key: value for item in iterable}। एक फिल्टर जोड़ें if के साथ, सूची कम्प्रिहेंशन की तरह समान।
names = ["alice", "bob", "carol"]
scores = [87, 74, 92]
score_map = {name: score for name, score in zip(names, scores)}
# {"alice": 87, "bob": 74, "carol": 92}एक फिल्टर के साथ:
passing = {name: score for name, score in score_map.items() if score >= 80}
# {"alice": 87, "carol": 92}words = ["apple", "banana", "cherry"]
word_lens = {word: len(word) for word in words}
# {"apple": 5, "banana": 6, "cherry": 6}{key: value for item in iterable} एक लाइन में एक डिक्शनरी बनाता है, समान आकार कुंजी और मान के बीच कोलन के साथ एक सूची कम्प्रिहेंशन के रूप में। इसे .items() के साथ एक डिक्ट को फिर से आकार देने के लिए जोड़ी करें जो आपके पास पहले से है, या दो सूचियों को एक नक्शे में सिलाई देने के लिए zip() के साथ। केवल जोड़ियों को रखने के लिए अंत में एक `if` जोड़ें। सेट कम्प्रिहेंशन
सेट कम्प्रिहेंशन एक सेट को एक एक्सप्रेशन में बनाते हैं, कोलन के बिना कर्ली ब्रेस के साथ। क्योंकि परिणाम एक सेट है, डुप्लिकेट स्वचालित रूप से हटा दिए जाते हैं।
words = ["apple", "banana", "cherry", "apple"]
unique = {w.lower() for w in words} # {"apple", "banana", "cherry"}सेट कम्प्रिहेंशन का उपयोग तब करें जब आप अद्वितीय मान चाहते हैं और ऑर्डर की परवाह न करें।
{expr for item in iterable} कोलन के बिना कर्ली ब्रेस के साथ एक सेट बनाता है, और एक सेट मुफ्त में डुप्लिकेट फेंकता है। इसलिए अगर आपका काम "मुझे अद्वितीय देने" है, यह इसे एक लाइन में करता है। हालांकि आने वाले किसी विशेष आदेश पर भरोसा न करें। जनरेटर एक्सप्रेशन
जनरेटर सूची कम्प्रिहेंशन की तरह दिखते हैं कोष्ठक के साथ कोष्ठक के बजाय। मुख्य अंतर: एक सूची कम्प्रिहेंशन पूरी सूची को एक बार मेमोरी में बनाता है। एक जनरेटर मान को एक बार में, केवल जब जरूरत हो, उत्पादन करता है। बड़े सीक्वेंस के लिए, यह कहीं अधिक कम मेमोरी का उपयोग करता है।
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)) बन जाता है। * ऑपरेटर फंक्शन चैप्टर में कवर किया गया है।
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})")zip() दो या अधिक सीक्वेंस को जोड़ता है इसलिए आप उन्हें एक साथ लूप कर सकते हैं, कोई इंडेक्स जुगालिंग नहीं। यह सबसे छोटे पर रुकता है, तो मिलान न करने वाली लंबाई चुप्पी से अतिरिक्त खो देती हैं। और `zip(*pairs)` इसे रिवर्स में चलाता है, जोड़ी की एक सूची को अलग सूचियों में वापस विभाजित करता है। map() और filter()
map() और filter() पुरानी कार्यात्मक-शैली के उपकरण हैं जो कम्प्रिहेंशन क्या करते हैं। आप पुराने कोड में उन्हें देखेंगे, इसलिए यह जानने के लायक है कि वे क्या मतलब रखते हैं। नए कोड के लिए कम्प्रिहेंशन को प्राथमिकता दें; वे अधिकांश पायथन डेवलपर्स के लिए अधिक पठनीय हैं।
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]कम्प्रिहेंशन को प्राथमिकता दें; वे अधिकांश पायथन डेवलपर्स को अधिक पठनीय हैं। 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}")
