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

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

docs.scrimba.com

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

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

ये सभी उपकरण एक ट्रांसफॉर्मेशन को एक एक्सप्रेशन (कोड का एक टुकड़ा जो एक मान का मूल्यांकन करता है) के रूप में व्यक्त करते हैं एक अनिवार्य लूप के बजाय जो एक परिणाम को चरण दर चरण बनाता है। लैम्डा आपको एक छोटा अनाम फ़ंक्शन इनलाइन देता है। कम्प्रिहेंशन एक पास में कलेक्शन बनाते हैं। जनरेटर आलसी हैं (वे सभी एक बार के बजाय आवश्यकतानुसार मान का उत्पादन करते हैं), इसलिए वे पूरे सीक्वेंस के बजाय मेमोरी में एक आइटम रखते हैं। zip कई सीक्वेंस को कदम में चलाता है। भुगतान यह है कि कोड "मुझे क्या चाहिए" के रूप में पढ़ता है इसके बजाय "इसे कैसे असेंबल करें", जब तक आप रुकते हैं इससे पहले कि वन-लाइनर अपठनीय हो जाए।

लैम्डा फंक्शन

एक लैम्डा एक अनाम, एक-एक्सप्रेशन फ़ंक्शन है। आप इसे lambda कीवर्ड से बनाते हैं। इसकी वास्तविक उपयोगिता यह है कि आप इसे इनलाइन लिख सकते हैं, बिल्कुल वहीं जहां आपको इसकी जरूरत है, पहले एक अनाम फ़ंक्शन परिभाषित किए बिना। यह है जो इसे sorted() के साथ उपयोगी बनाता है।

एक लैम्डा एक अनाम सिंगल-एक्सप्रेशन फ़ंक्शन है। यह कई आर्गुमेंट ले सकता है लेकिन इसका बॉडी एक एक्सप्रेशन होना चाहिए, एक स्टेटमेंट नहीं। इसका प्राथमिक उपयोग एक इनलाइन key= या कॉलबैक आर्गुमेंट के रूप में है जहां एक पूर्ण def केवल अनावश्यक अप्रत्यक्षता जोड़ेगा। कुछ और जटिल के लिए, def का उपयोग करें।

एक लैम्डा वही फ़ंक्शन ऑब्जेक्ट है जो def प्रोड्यूस करता है, तीन सीमाओं के साथ: इसका कोई नाम नहीं है (यह एक ट्रेसबैक में <lambda> दिखाता है, त्रुटि रिपोर्ट जो पायथन प्रिंट करता है जब कुछ उठता है), इसका बॉडी एक एक्सप्रेशन है इसलिए यह स्टेटमेंट नहीं रख सकता, और यह कोई डॉकस्ट्रिंग नहीं रखता। पिटफॉल जो वास्तविक डिबगिंग समय की लागत करता है वह है क्लोजर में लेट बाइंडिंग (एक फ़ंक्शन जो अपने चारों ओर स्कोप से एक वेरिएबल को कैप्चर करता है)। एक लूप के अंदर बनाया गया लैम्डा लूप वेरिएबल को संदर्भ से कैप्चर करता है, इसलिए हर लैम्डा वेरिएबल का अंतिम मान देखता है, उस मान को नहीं जो लैम्डा के बनाए जाने के समय था:

python
# फंक्शन = [lambda: i for i in range(3)]
# print([f() for f in funcs])        # [2, 2, 2], [0, 1, 2] नहीं

# funcs = [lambda i=i: i for i in range(3)]
# print([f() for f in funcs])        # [0, 1, 2]: i=i अभी मान को बांधता है

i=i ट्रिक वर्तमान मान को निर्माण समय में डिफ़ॉल्ट आर्गुमेंट के रूप में पिन करता है। लूप में कॉलेबल बनाते समय इसके लिए पहुंचें।

python
double = lambda x: x * 2
double(5)   # 10

यह बराबर है:

python
def double(x):
    return x * 2

अधिकांश मामलों के लिए, def का उपयोग करें। लैम्डा का एक वास्तविक लाभ है: आप उन्हें इनलाइन लिख सकते हैं, बिल्कुल वहीं जहां आपको उनकी जरूरत है, उन्हें नाम दिए बिना। यह है जो उन्हें sorted(), map() और filter() के साथ उपयोगी बनाता है:

python
players = [("अनिल", 87), ("भारत", 74), ("चारु", 92)]

sorted(players, key=lambda p: p[1])              # स्कोर से सॉर्ट करें (आरोही)
sorted(players, key=lambda p: p[1], reverse=True)  # स्कोर से सॉर्ट करें (अवरोही)

लैम्डा के बिना, आपको key= आर्गुमेंट के लिए केवल एक अनाम फ़ंक्शन परिभाषित करना होगा। लैम्डा इरादे को स्थानीय और दृश्यमान रखता है।

लैम्डा कई आर्गुमेंट ले सकते हैं:

python
add = lambda a, b: a + b
add(3, 4)   # 7

लैम्डा का उपयोग कब करें: केवल जब यह एक छोटी एक्सप्रेशन है जो एक जगह में उपयोग की जाती है। अगर यह बढ़ रहा है, या आपको इसे फिर से उपयोग करना है, एक उचित def लिखें। एक लैम्डा जो कई ऑपरेटर में फैला हो या एक शर्तीय की जरूरत है आमतौर पर def पर स्विच करने का संकेत है।

Junoलैम्डा फंक्शन एक लैम्डा एक छोटा एक-लाइन फंक्शन है जिसका कोई नाम नहीं है, lambda कीवर्ड के साथ लिखा गया है। इसका पूरा अस्तित्व का कारण `sorted()` के लिए key= के रूप में इनलाइन जाना है ताकि आप एक अलग फंक्शन को एक काम के लिए परिभाषित न करें। जिस क्षण यह एक साफ एक्सप्रेशन से लंबा हो जाता है, मैं एक असली `def` लिखता हूं और इसे लेकर बेहतर महसूस करता हूं।
Junoलैम्डा फंक्शन एक लैम्डा एक अनाम सिंगल-एक्सप्रेशन फंक्शन है, एक इनलाइन `key=` या कॉलबैक के रूप में काम में आता है जहां एक नाम वाला `def` केवल शोर जोड़ेगा। बॉडी एक एक्सप्रेशन है, कोई स्टेटमेंट अनुमति नहीं है। कुछ और जटिल के लिए, `def` के लिए पहुंचें।
Junoलैम्डा फंक्शन `def` के समान फंक्शन ऑब्जेक्ट, एक नाम, स्टेटमेंट और एक डॉकस्ट्रिंग को घटा कर, इसलिए उन्हें एक-लाइनर `key=` के लिए रखें। जाल लेट बाइंडिंग है: एक लूप में बनाया गया लैम्डा लूप वेरिएबल का अंतिम मान पढ़ता है, इसलिए `lambda i=i: i` लिखें इसे पिन करने के लिए। वह एक बार सभी को काटता है।

सूची कम्प्रिहेंशन

पायथन में सबसे सामान्य ट्रांसफॉर्मेशन: एक सीक्वेंस लें, हर आइटम पर कुछ करें, एक नई सूची वापस पाएं। एक सूची कम्प्रिहेंशन यह एक पठनीय लाइन में करता है: [expression for item in iterable]। आप एक शर्त के साथ if जोड़ सकते हैं।

सूची कम्प्रिहेंशन बिल्ड-विथ-अ-लूप पैटर्न के लिए एक संक्षिप्त प्रतिस्थापन हैं। वे आमतौर पर समान for लूप से तेज़ होते हैं .append() के साथ, क्योंकि पायथन हर पास पर एक विधि को कॉल नहीं करता। संरचना है [expression for item in iterable if condition]; if क्लॉज वैकल्पिक है।

एक कम्प्रिहेंशन समान लूप को बुलाते हुए .append() हर पास पर अर्थपूर्ण रूप से तेज़ है, इसलिए यह एक ट्रांसफॉर्मेशन से एक सूची बनाने का अनुकूल तरीका है। यह अपने स्वयं के स्कोप में भी चलता है (क्षेत्र जहां एक नाम दृश्यमान है), जिसका अर्थ है लूप वेरिएबल आसपास के कोड में लीक नहीं होता: [n ** 2 for n in numbers] के बाद, नाम n कम्प्रिहेंशन के बाहर मौजूद नहीं है। पकड़ जो देखने के लिए है वह एक जगह पहुंचना है जहां बॉडी असली काम करता है। एक बार एक्सप्रेशन एक सफाई ट्रांसफॉर्मेशन से परे बढ़ता है, या आप लॉगिंग या ट्राई ब्लॉक जोड़ना चाहते हैं, स्पष्ट लूप बेहतर उपकरण है, क्योंकि एक कम्प्रिहेंशन केवल एक एक्सप्रेशन रख सकता है, कभी एक स्टेटमेंट नहीं।

लंबा तरीका:

python
numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
    squares.append(n ** 2)

सूची कम्प्रिहेंशन:

python
squares = [n ** 2 for n in numbers]

संरचना हमेशा समान है: [expression for item in iterable]

python
scores = [87, 42, 96, 55, 71]
scaled = [s * 1.1 for s in scores]          # 10% बोनस लागू करें
as_grades = [f"{s}/100" for s in scores]    # हर एक को फॉर्मेट करें
Junoसूची कम्प्रिहेंशन[expression for item in iterable] एक सीक्वेंस लेता है, हर आइटम पर एक काम करता है, और आपको एक नई सूची वापस देता है। इसे बाएं से दाएं पढ़ें और यह बिल्कुल कहता है कि यह क्या करता है। यह पहली पायथन फीचर थी जिसने मुझे महसूस कराया कि मैं पायथन लिख रहा हूं दूसरी भाषा से अनुवाद करने के बजाय।
Junoसूची कम्प्रिहेंशन[expression for item in iterable] बिल्ड-विथ-अ-लूप-एंड-.append() पैटर्न को बदलता है, और इसे अधिक साफ रूप से पढ़ता है। यह एक नई सूची बनाता है और कुछ भी म्यूट नहीं करता। एक्सप्रेशन को सरल रखें, अन्यथा पठनीयता जो आपने हासिल की है वह चली जाएगी।
Junoसूची कम्प्रिहेंशन `.append()` लूप से तेज़ और यह अपने स्वयं के स्कोप में चलता है, इसलिए लूप वेरिएबल कभी लीक नहीं होता। लाइन को होल्ड करें: एक कम्प्रिहेंशन एक एक्सप्रेशन लेता है, एक स्टेटमेंट नहीं, इसलिए दूसरे पल आप एक ट्राई ब्लॉक या लॉग लाइन चाहते हैं, स्पष्ट लूप जीतता है।

एक शर्त के साथ फ़िल्टर करना

केवल आइटम शामिल करने के लिए एक if क्लॉज जोड़ें जो एक परीक्षा पास करते हैं। परिणाम एक नई सूची है जिसमें केवल वे आइटम हैं जहां शर्त True है।

एक कम्प्रिहेंशन में if क्लॉज एक फिल्टर है, एक if/else नहीं। यह हर आइटम पर एक बार चलता है और केवल आइटम शामिल करता है जिसके लिए शर्त सत्य है। एक सशर्त ट्रांसफॉर्मेशन के लिए (एक शर्त के आधार पर एक मान को दूसरे में मैप करें), मुख्य एक्सप्रेशन के अंदर एक त्रिगुण एक्सप्रेशन का उपयोग करें।

if की स्थिति तय करती है कि क्या आप फिल्टर या ट्रांसफॉर्म करते हैं, और उन्हें मिक्स करना गलत-लंबाई परिणाम का एक सामान्य कारण है। अंत में एक if फिल्टर करता है: [x for x in data if x > 0] आइटम गिराता है। एक सशर्त सामने नक्शे: [x if x > 0 else 0 for x in data] हर आइटम को रखता है और विफलता वाले को फिर से लिखता है (यहां, नकारात्मक को शून्य पर कैलम्प करना)। आप एक कम्प्रिहेंशन में दोनों को संयोजित कर सकते हैं, [x * 2 for x in data if x > 0], और कई ट्रेलिंग if क्लॉज स्टैक कर सकते हैं, जो and के रूप में एक साथ आते हैं।

python
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]
python
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]
Junoएक शर्त के साथ फ़िल्टर करना केवल आइटम को रखने के लिए अंत में if condition जोड़ें जो परीक्षा पास करते हैं: [x for x in data if x > 0]। कुछ भी जो गलत आता है नई सूची से बाहर रहता है। समान कम्प्रिहेंशन जो आप पहले से जानते हैं, इसके साथ एक दरवाजा व्यक्ति है।
Junoएक शर्त के साथ फ़िल्टर करना एक ट्रेलिंग if फिल्टर करता है, केवल उन आइटम को रखते हुए जहां शर्त सत्य है। यह एक्सप्रेशन के अंदर एक सशर्त से अलग है: [x if x > 0 else 0 for x in data] उन्हें गिरा कर बजाय मान को फिर से लिखता है। इसे लिखने से पहले जानें कि आप कौन सा चाहते हैं।
Junoएक शर्त के साथ फ़िल्टर करना अंत में if फिल्टर करता है और लंबाई बदलता है; सामने एक सशर्त नक्शे और इसे रखता है। दोनों को भ्रमित करें और आप एक परिणाम भेजते हैं जो गलत आकार है। स्टैक किए गए ट्रेलिंग if क्लॉज and के साथ चेन करते हैं।

नेस्टेड कम्प्रिहेंशन

आइटम की एक सूची को एक एकल सूची में समतल करने के लिए आप कम्प्रिहेंशन को नेस्ट कर सकते हैं। इसे बाएं से दाएं पढ़ें: हर पंक्ति के लिए, उस पंक्ति में हर आइटम के लिए, आइटम को शामिल करें।

नेस्टेड कम्प्रिहेंशन बाएं से दाएं निष्पादित होते हैं। पहली for क्लॉज बाहरी लूप है, दूसरी आंतरिक है। वे एक एकल सपाट परिणाम बनाते हैं, एक 2डी संरचना नहीं। अगर कम्प्रिहेंशन पढ़ने में मुश्किल है, लूप को स्पष्ट रूप से लिखें।

क्लॉज ऑर्डर समान नेस्टेड लूप के रूप में पढ़ता है: पहली for बाहरी लूप है, दूसरी आंतरिक है, और एक बाद की क्लॉज एक पहले की बाई एक नाम बाँध सकती है। जहां यह अपना अर्थ प्राप्त करता है वह समतल है; जहां यह चोट पहुंचाता है वह सत्य ग्रिड संयोजन (दो सीक्वेंस से हर जोड़ी), जिसके लिए itertools.product एक डबल for के मुकाबले बहुत स्पष्ट पढ़ता है। नियम जो एक कोडबेस को स्वस्थ रखता है: अगर कम्प्रिहेंशन को पार्स करने में आपको एक सेकंड से अधिक समय लगता है, स्पष्ट लूप बेहतर दस्तावेज़ है, इसलिए इसके बजाय लिखें।

python
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]

इसे बाएं से दाएं पढ़ें: मैट्रिक्स में हर पंक्ति के लिए, पंक्ति में हर आइटम के लिए, आइटम को शामिल करें।

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

Junoनेस्टेड कम्प्रिहेंशन एक कम्प्रिहेंशन में दो for क्लॉज एक सूची सूची को एक एकल सपाट सूची में समतल करते हैं: [item for row in matrix for item in row]। इसे बाएं से दाएं, बाहरी लूप पहले पढ़ें, बिल्कुल वैसी ही क्रम में जैसे आप लूप लिखेंगे। अगर आपकी आंखें इस पर अटक जाती हैं, यह असली लूप लिखने का संकेत है।
Junoनेस्टेड कम्प्रिहेंशन दो `for` क्लॉज स्टैक करें और पहली बाहरी लूप है, दूसरी आंतरिक: [item for row in matrix for item in row] 2D सूची को एक में समतल करता है। परिणाम सपाट है, एक ग्रिड नहीं। जब यह एक नज़र में पठनीय होना बंद कर दे, स्पष्ट लूप बेहतर हैं।
Junoनेस्टेड कम्प्रिहेंशन पहली `for` बाहरी लूप है, और एक बाद की क्लॉज एक पहले से एक नाम का उपयोग कर सकती है। समतल करने के लिए अच्छा, हर-जोड़ी संयोजन के लिए खराब, जहां `itertools.product` स्पष्ट पढ़ता है। अगर इसे पार्स करने में एक सेकंड से अधिक समय लगता है, लूप बेहतर दस्तावेज़ है।

डिक्ट कम्प्रिहेंशन

डिक्ट कम्प्रिहेंशन एक डिक्शनरी को एक एक्सप्रेशन में बनाते हैं, सूची कम्प्रिहेंशन के समान विचार का उपयोग करते हुए: {key: value for item in iterable}। एक फिल्टर जोड़ें if के साथ, सूची कम्प्रिहेंशन की तरह समान।

डिक्ट कम्प्रिहेंशन कुंजी-मान जोड़ी बनाने वाले किसी भी इटेरेबल से एक नई डिक्ट बनाते हैं। सिंटैक्स है {key_expr: val_expr for item in iterable if condition}। लूप से डुप्लिकेट कुंजियां अंतिम मान का उपयोग करती हैं, चुप्पी से। मौजूदा डिक्ट पर .items() डिक्ट कम्प्रिहेंशन के लिए सबसे सामान्य स्रोत इटेरेबल है।

दो चीजें वास्तविक कोड में काटती हैं। पहली, हर कुंजी हैशेबल होनी चाहिए (एक मान पायथन को एक निश्चित लुकअप संख्या में कम कर सकता है, जिसका अर्थ है यह कभी नहीं बदलता, इसलिए स्ट्रिंग और संख्या और ट्यूपल योग्य हैं लेकिन सूची और डिक्ट नहीं)। एक कुंजी एक्सप्रेशन जो एक सूची देता है TypeError उठाता है। दूसरी, डुप्लिकेट कुंजियां त्रुटि नहीं देती: अगर लूप समान कुंजी दो बार बनाता है, बाद का मान चुप्पी से पहले को ओवरराइट करता है, जो डेटा से डिक्ट बनाते समय गिराए गए डेटा का एक शांत स्रोत है जो वास्तव में अद्वितीय नहीं है। जब आप केवल दो मौजूदा डिक्ट को मर्ज करना चाहते हैं, | ऑपरेटर (डिक्ट-मर्ज फॉर्म, पायथन 3.9 और ऊपर) एक कम्प्रिहेंशन से इरादे को अधिक स्पष्ट रूप से स्टेट करता है।

python
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}

एक फिल्टर के साथ:

python
passing = {name: score for name, score in score_map.items() if score >= 80}
# {"alice": 87, "carol": 92}
python
words = ["apple", "banana", "cherry"]
word_lens = {word: len(word) for word in words}
# {"apple": 5, "banana": 6, "cherry": 6}
Junoडिक्ट कम्प्रिहेंशन{key: value for item in iterable} एक लाइन में एक डिक्शनरी बनाता है, समान आकार कुंजी और मान के बीच कोलन के साथ एक सूची कम्प्रिहेंशन के रूप में। इसे .items() के साथ एक डिक्ट को फिर से आकार देने के लिए जोड़ी करें जो आपके पास पहले से है, या दो सूचियों को एक नक्शे में सिलाई देने के लिए zip() के साथ। केवल जोड़ियों को रखने के लिए अंत में एक `if` जोड़ें।
Junoडिक्ट कम्प्रिहेंशन{key: value for item in iterable} किसी भी जोड़ी के स्रोत से एक डिक्ट बनाता है। दो रोजमर्रा के स्रोत एक मौजूदा डिक्ट पर `items()` और दो सूचियों पर `zip()` हैं। डुप्लिकेट कुंजियों के लिए देखें: अंतिम वाली जीतती है, चुप्पी से।
Junoडिक्ट कम्प्रिहेंशन कुंजियां हैशेबल होनी चाहिए (कोई सूची नहीं), और डुप्लिकेट कुंजियां त्रुटि नहीं देती, बाद का मान चुप्पी से ओवरराइट करता है, जो डेटा खाता है जब आपका स्रोत अद्वितीय नहीं है। दो डिक्ट मर्ज करने से पहले, विशिष्टता की जांच करें। `|` एक कम्प्रिहेंशन से अधिक स्पष्ट कहता है।

सेट कम्प्रिहेंशन

सेट कम्प्रिहेंशन एक सेट को एक एक्सप्रेशन में बनाते हैं, कोलन के बिना कर्ली ब्रेस के साथ। क्योंकि परिणाम एक सेट है, डुप्लिकेट स्वचालित रूप से हटा दिए जाते हैं।

सेट कम्प्रिहेंशन {expression for item in iterable} का उपयोग करते हैं और एक set बनाते हैं। वे स्वचालित रूप से डुप्लिकेट करते हैं। उन्हें तब उपयोग करें जब आपको एक अद्वितीय कलेक्शन की जरूरत हो एक ट्रांसफॉर्मेशन से बना हो, जहां ऑर्डर मायने नहीं रखता।

परिणाम एक set है, इसलिए दो चीजें अनुसरण करती हैं जो सूची संस्करण आपको नहीं देता। एक्सप्रेशन से डुप्लिकेट मान स्वचालित रूप से एक में ढह जाते हैं, जो बिंदु है: यह एक एकल एक्सप्रेशन में ट्रांसफॉर्मेशन को डीडुप करने का सबसे साफ तरीका है। लागत यह है कि एक सेट का कोई आदेश नहीं है, इसलिए आप आइटम को किसी विशेष क्रम में बाहर आने पर भरोसा नहीं कर सकते। सदस्यों को भी हैशेबल होना चाहिए, वही नियम जो डिक्ट कुंजियों पर लागू होते हैं: एक मान पायथन को एक निश्चित लुकअप संख्या में कम कर सकता है, जो सूची को नियम कर देता है।

python
words = ["apple", "banana", "cherry", "apple"]
unique = {w.lower() for w in words}    # {"apple", "banana", "cherry"}

सेट कम्प्रिहेंशन का उपयोग तब करें जब आप अद्वितीय मान चाहते हैं और ऑर्डर की परवाह न करें।

Junoसेट कम्प्रिहेंशन{expr for item in iterable} कोलन के बिना कर्ली ब्रेस के साथ एक सेट बनाता है, और एक सेट मुफ्त में डुप्लिकेट फेंकता है। इसलिए अगर आपका काम "मुझे अद्वितीय देने" है, यह इसे एक लाइन में करता है। हालांकि आने वाले किसी विशेष आदेश पर भरोसा न करें।
Junoसेट कम्प्रिहेंशन{expr for item in iterable} एक `set` बनाता है, जाते हुए डुप्लिकेट करता है। जब आप एक अद्वितीय कलेक्शन चाहते हैं एक ट्रांसफॉर्मेशन से और आदेश मायने नहीं रखता तो इसके लिए पहुंचें। कर्ली ब्रेस कोलन के बिना, यही एकमात्र चीज है जो इसे डिक्ट कम्प्रिहेंशन से अलग करती है।
Junoसेट कम्प्रिहेंशन सेट डुप्लिकेट स्वचालित रूप से गिराता है, जो पूरा कारण है कि इसे सूची कम्प्रिहेंशन पर उठा लें। व्यापार कोई ऑर्डर नहीं है भरोसा करने के लिए, और सदस्य हैशेबल होने चाहिए, तो सूची के अंदर कोई नहीं। सर्वश्रेष्ठ फिट: एक एक्सप्रेशन में ट्रांसफॉर्मेशन को डीडुप करें।

जनरेटर एक्सप्रेशन

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

एक जनरेटर एक्सप्रेशन एक इटेरेटर बनाता है, एक कलेक्शन नहीं। यह आलसी मूल्यों की गणना करता है: अगला मान केवल तब बनाया जाता है जब अनुरोध किया जाए। यह सबसे मूल्यवान है जब परिणाम sum(), max() या any() जैसे फंक्शन द्वारा तुरंत खपत किया जाता है, तो पहले पूरी सूची बनाने का कोई मतलब नहीं है।

एक जनरेटर मान आलसी (एक बार एक बार, केवल जब कुछ अगला पूछे) बनाता है, इसलिए इसकी मेमोरी इनपुट कितना भी बड़ा हो रहता है: यह कभी भी वर्तमान मान से अधिक नहीं रखता है, जहां एक सूची कम्प्रिहेंशन हर एक्सप्रेशन एक बार में रखता है। यह sum(), max() या any() में सीधे खिलाने वाले बड़े या स्ट्रीमिंग स्रोत के लिए सही कॉल बनाता है। विफलता मोड को याद रखना है कि एक जनरेटर एकल-उपयोग है: एक बार कुछ इसे अंत तक दोहराता है, यह समाप्त है और कुछ नहीं देता, तो समान जनरेटर पर दूसरा लूप शून्य बार चलता है और कोई त्रुटि नहीं देता। अगर आपको दो बार डेटा चलाने की जरूरत है, एक बार सूची बनाएं और इसे दोहराएं।

python
squares_gen = (n ** 2 for n in range(1000000))
python
total = sum(n ** 2 for n in range(1000000))   # sum() जनरेटर को खपत करता है

जब एक जनरेटर को सीधे sum(), max(), min() या any() जैसे फंक्शन में पास करते हैं, तो आप अतिरिक्त कोष्ठक गिरा सकते हैं:

python
total = sum(n ** 2 for n in range(1000))   # एक सेट पैरेन, दो नहीं

अधिकांश रोजमर्रा के कोड के लिए, सूची कम्प्रिहेंशन ठीक हैं। जनरेटर का उपयोग करें जब आप बड़े डेटासेट या स्ट्रीमिंग डेटा को संसाधित कर रहे हैं जहां सब कुछ मेमोरी में पकड़ना अपशिष्ट होगा।

Junoजनरेटर एक्सप्रेशन एक जनरेटर कोष्ठक के साथ एक सूची कम्प्रिहेंशन की तरह दिखता है वर्ग कोष्ठक के बजाय, लेकिन यह पहले से पूरी सूची बनाने के बजाय मान को एक बार में बनाता है। एक विशाल सीक्वेंस के लिए मेमोरी की एक ढेर बचाता है। साफ मामला: एक को सीधे `sum()` या `max()` में गिराएं और सूची बनाना पूरी तरह छोड़ दें।
Junoजनरेटर एक्सप्रेशन एक जनरेटर एक्सप्रेशन एक आलसी इटेरेटर देता है: यह अगला मान केवल तब कंप्यूट करता है जब पूछा जाए, इसलिए कुछ भी पूरी सूची को मेमोरी में नहीं बनाता। सर्वश्रेष्ठ जब परिणाम `sum()`, `max()` या `any()` में सीधे खिलाया जाता है। याद रखें कि यह एकल-उपयोग है, एक बार खपत किया जाता है यह खाली है।
Junoजनरेटर एक्सप्रेशन आलसी और इनपुट कितना भी बड़ा हो मेमोरी में सपाट, इसलिए यह `sum()` या `any()` में एक बड़े या स्ट्रीमिंग स्रोत के लिए सही उपकरण है। पकड़: यह एकल-उपयोग है, और समाप्त जनरेटर पर दूसरा लूप शून्य बार चलता है कोई त्रुटि के बिना। दो पास की जरूरत? एक बार सूची बनाएं।

zip()

zip() दो या अधिक सीक्वेंस से आइटम को एक साथ जोड़ता है इसलिए आप उन्हें समानांतर में लूप कर सकते हैं। यह सबसे छोटे सीक्वेंस पर रुकता है। जब दो सूचियां एक दूसरे से संबंधित होती हैं तो इंडेक्स प्रबंधन से बचने का यह साफ तरीका है।

zip() ट्यूपल का एक आलसी इटेरेटर देता है, इनपुट इटेरेबल को कदम में खपत करता है। यह सबसे छोटे इनपुट पर रुकता है: लंबे सीक्वेंस चुप्पी से छंटनी हैं। सीक्वेंस जो लंबाई में भिन्न हो सकते हैं, itertools.zip_longest() छोटे को एक निर्दिष्ट मान से भरता है।

zip() अपने इनपुट को कदम में चलाता है और सबसे छोटा पल से रुकता है। वह ट्रंकेशन गॉचा है डिज़ाइन करने के लिए: 1000 रिकॉर्ड की एक सूची को 999 की सूची के साथ जोड़ी करें और आप चुप्पी से अंतिम रिकॉर्ड खो देते हैं, कोई त्रुटि नहीं, कोई चेतावनी नहीं। जब लंबाई मेल खानी चाहिए, zip(seq_a, seq_b, strict=True) (पायथन 3.10 और ऊपर) डेटा गिराने के बजाय अगर वे भिन्न हैं तो उठाता है, और itertools.zip_longest अंतराल को भरता है जब वे भिन्न होने की अनुमति हैं। अन्य ट्रिक जो जानने के लायक है: zip(*rows) ट्रांसपोज़ करता है, पंक्तियों की एक सूची को कॉलम की सूची में बदलते हैं, क्योंकि * बाहरी सूची को अलग आर्गुमेंट में अनपैक करता है।

python
names = ["अनिल", "भारत", "चारु"]
scores = [87, 74, 92]

for name, score in zip(names, scores):
    print(f"{name}: {score}")
# अनिल: 87
# भारत: 74
# चारु: 92

zip() सबसे छोटे सीक्वेंस पर रुकता है। अगर आपके सीक्वेंस अलग लंबाई के हो सकते हैं, तो एक भरण मान के साथ itertools.zip_longest() का उपयोग करें।

जोड़ी की एक ज़िप की गई सूची से दो अलग सूचियों में वापस कन्वर्ट करने के लिए, zip(*pairs) का उपयोग करें:

python
pairs = [("अनिल", 87), ("भारत", 74), ("चारु", 92)]
names, scores = zip(*pairs)
# names = ("अनिल", "भारत", "चारु")
# scores = (87, 74, 92)

*pairs सूची को अलग आर्गुमेंट में अनपैक करता है, इसलिए zip(*pairs) zip(("अनिल", 87), ("भारत", 74), ("चारु", 92)) बन जाता है। * ऑपरेटर फंक्शन चैप्टर में कवर किया गया है।

zip() समानांतर में कई सीक्वेंस को दोहराने के लिए भी साफ तरीका है बिना मैनुअल रूप से इंडेक्स प्रबंधन किए:

python
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})")
Junozip()zip() दो या अधिक सीक्वेंस को जोड़ता है इसलिए आप उन्हें एक साथ लूप कर सकते हैं, कोई इंडेक्स जुगालिंग नहीं। यह सबसे छोटे पर रुकता है, तो मिलान न करने वाली लंबाई चुप्पी से अतिरिक्त खो देती हैं। और `zip(*pairs)` इसे रिवर्स में चलाता है, जोड़ी की एक सूची को अलग सूचियों में वापस विभाजित करता है।
Junozip() `zip()` ट्यूपल का एक आलसी इटेरेटर देता है, अपने इनपुट को समानांतर में stepping। यह सबसे छोटे पर रुकता है, तो लंबी सीक्वेंस बिना किसी peep के छंटनी हैं। `itertools.zip_longest()` अंतराल को भरता है जब लंबाई वैध रूप से भिन्न होती है, और `zip(*pairs)` अनजिप करता है।
Junozip() आलसी, समानांतर, और सबसे छोटे इनपुट पर रुकता है, जो चुप्पी से डेटा गिराता है जब लंबाई मेल खानी थी। एक मिलान को उठाने के लिए `strict=True` पास करें। `zip(*rows)` आपका ट्रांसपोज़ है, एक कॉल में पंक्तियों से कॉलम।

map() और filter()

map() और filter() पुरानी कार्यात्मक-शैली के उपकरण हैं जो कम्प्रिहेंशन क्या करते हैं। आप पुराने कोड में उन्हें देखेंगे, इसलिए यह जानने के लायक है कि वे क्या मतलब रखते हैं। नए कोड के लिए कम्प्रिहेंशन को प्राथमिकता दें; वे अधिकांश पायथन डेवलपर्स के लिए अधिक पठनीय हैं।

map(func, iterable) एक आलसी इटेरेटर देता है जो प्रत्येक आइटम पर func लागू करता है। filter(func, iterable) एक आलसी इटेरेटर देता है उन आइटम के लिए जिनके लिए func सत्य है। दोनों कम्प्रिहेंशन से पहले आते हैं। नए कोड में कम्प्रिहेंशन को प्राथमिकता दें; map() का उपयोग करें जब आपके पास पहले से एक अनाम फंक्शन है जो आपको क्या चाहिए।

दोनों आलसी इटेरेटर देते हैं, सूची नहीं, इसलिए जब आप अब मान चाहते हैं तो उन्हें list() में लपेटें। वे कम्प्रिहेंशन पर मैप एक-एक: map(f, it) है (f(x) for x in it), और filter(pred, it) है (x for x in it if pred(x))। वह समतुल्यता निर्णय नियम है। एक इनलाइन lambda के साथ, कम्प्रिहेंशन बेहतर पढ़ता है और आधुनिक डिफ़ॉल्ट है। एक अनाम फंक्शन के साथ जो पहले से काम करता है, list(map(int, strings)) "सीक्वेंस पर int को नक्शा" के रूप में पढ़ता है और साफ विकल्प है, तो एकमात्र असली कॉल क्या है कि क्या आपके पास पहले से एक फंक्शन हाथ में है।

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]

कम्प्रिहेंशन को प्राथमिकता दें; वे अधिकांश पायथन डेवलपर्स को अधिक पठनीय हैं। map() का उपयोग करें जब आपके पास एक अनाम फंक्शन है जो पहले से मौजूद है:

python
strings = ["1", "2", "3"]
numbers = list(map(int, strings))   # [1, 2, 3] (एक कम्प्रिहेंशन से यहाँ साफ़)
Junomap() और filter() `map(func, iterable)` हर आइटम पर एक फंक्शन चलाता है; `filter(func, iterable)` केवल वे आइटम रखता है जहां फंक्शन सत्य आता है। वे पुरानी तरीका है जो कम्प्रिहेंशन करते हैं, तो आप उन्हें दूसरे लोगों के कोड में मिलेंगे। आपके स्वयं के लिए, एक कम्प्रिहेंशन अधिकांश लोगों को अधिक साफ पढ़ता है।
Junomap() और filter() `map()` प्रत्येक आइटम को ट्रांसफॉर्म करता है, `filter()` सत्य वाले को रखता है, दोनों आलसी तो परिणाम देखने के लिए `list()` में लपेटें। नए कोड के लिए कम्प्रिहेंशन डिफ़ॉल्ट है। एक जगह `map()` जीतता है एक अनाम फंक्शन है जो आपके पास पहले से है: `map(int, strings)` कम्प्रिहेंशन से साफ पढ़ता है।
Junomap() और filter() `map(f, it)` है `(f(x) for x in it)` और `filter(pred, it)` है `(x for x in it if pred(x))`, दोनों आलसी। तो विकल्प शुद्ध रूप से पठनीयता है: एक इनलाइन लैम्डा के साथ, कम्प्रिहेंशन जीतता है; एक अनाम फंक्शन के साथ पहले से ही नाम, `map(int, strings)` जीतता है।

अभ्यास में

एक प्लेयर सूची को पास स्कोर में फ़िल्टर करें, sorted और एक लैम्डा के साथ स्कोर के अनुसार रैंक करें, फिर गणना की गई स्थिति के साथ प्रिंट करें:

python
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}")

सक्रिय एडमिन के लिए एक उपयोगकर्ता सूची को फ़िल्टर करें, एक आईडी-से-नाम लुकअप डिक्ट बनाएं, और एक पास में सॉर्ट किए गए नाम संग्रहीत करें:

python
raw_users = [
    {"id": 1, "name": "अनिल", "role": "admin", "active": True},
    {"id": 2, "name": "भारत", "role": "user", "active": False},
    {"id": 3, "name": "चारु", "role": "admin", "active": True},
    {"id": 4, "name": "दीपक", "role": "user", "active": True},
]

active_admins = [u for u in raw_users if u["active"] and u["role"] == "admin"]
id_map = {u["id"]: u["name"] for u in raw_users}
names = sorted(u["name"] for u in raw_users if u["active"])

print(f"Active admins: {[u['name'] for u in active_admins]}")
print(f"All active: {names}")

zip का उपयोग करके फीचर नामों को महत्व स्कोर के साथ जोड़ी करें, एक डिक्ट कम्प्रिहेंशन बनाएं, एक लैम्डा के साथ सॉर्ट करें, और दूसरी कम्प्रिहेंशन में मान को सामान्य करें:

python
feature_names = ["age", "income", "score", "tenure"]
importances = [0.12, 0.34, 0.28, 0.26]

feat_dict = {f: i for f, i in zip(feature_names, importances)}
top_feats = sorted(feat_dict.items(), key=lambda x: x[1], reverse=True)[:2]

print("शीर्ष 2 फीचर:")
for name, score in top_feats:
    print(f"  {name}: {score:.2f}")

# 1.0 को जोड़ करने के लिए सामान्य करें (यहाँ मान पहले से 1 तक जोड़ते हैं, लेकिन पैटर्न के रूप में दिखाया गया है)
total = sum(feat_dict.values())
normalised = {k: round(v / total, 4) for k, v in feat_dict.items()}
print(f"सामान्य: {normalised}")

zip मध्यवर्ती ट्यूपल बनाए बिना दो सूचियों को जोड़ता है। डिक्ट कम्प्रिहेंशन एक एक्सप्रेशन में नक्शा बनाता है। सॉर्ट लैम्डा एक अनाम कुंजी फंक्शन से बचता है। सामान्यकरण कम्प्रिहेंशन मूल डिक्ट को म्यूट किए बिना मान को ट्रांसफॉर्म करता है।