Python Language
सूची की समझ
खोज…
परिचय
[i ** 2 for i in range(1,11)]
एक मौजूदा सूची range
से डमी i
का उपयोग एक नया तत्व पैटर्न बनाने के लिए किया जाता है। यह प्रयोग किया जाता है जहां कम अभिव्यंजक भाषाओं में लूप के लिए आवश्यक होगा।
वाक्य - विन्यास
- [i in i for रेंज (10)] # मूल सूची समझ
- [i for i in xrange (10)] # बेसिक लिस्ट कॉम्प्रिहेंशन विथ जेनेरेटर ऑब्जेक्ट इन पाइथॉन 2.x
- [i for i in रेंज (20) यदि i% 2 == 0] # फ़िल्टर के साथ
- [x + y में x के लिए [1, 2, 3] में y के लिए [3, 4, 5]] # नेस्टेड लूप
- [i अगर मैं i (6) 0 के लिए मैं रेंज में (10)] # टर्नरी अभिव्यक्ति
- [i if i> रेंज में i के लिए ४ और ० (२०) अगर i% २ == ०] # फ़िल्टर और टर्नरी अभिव्यक्ति के साथ
- [[3, 4, 5] में y के लिए [1, 2, 3] में x के लिए [[x + y] # नेस्टेड सूची बोध
टिप्पणियों
पीईपी 202 में सूची समझ को उल्लिखित किया गया और पायथन 2.0 में पेश किया गया।
सशर्त सूची की समझ
एक को देखते हुए सूची समझ आप एक या अधिक जोड़ सकते हैं if
फिल्टर मूल्यों के लिए स्थिति।
[<expression> for <element> in <iterable> if <condition>]
प्रत्येक <element>
के लिए <iterable>
; यदि <condition>
True
मूल्यांकन करता है, तो लौटी हुई सूची में <expression>
(आमतौर पर <element>
का एक फंक्शन) जोड़ें।
उदाहरण के लिए, इसका उपयोग पूर्णांक के अनुक्रम से केवल संख्या निकालने के लिए किया जा सकता है:
[x for x in range(10) if x % 2 == 0]
# Out: [0, 2, 4, 6, 8]
उपरोक्त कोड इसके बराबर है:
even_numbers = []
for x in range(10):
if x % 2 == 0:
even_numbers.append(x)
print(even_numbers)
# Out: [0, 2, 4, 6, 8]
इसके अलावा, फॉर्म की एक सशर्त सूची [e for x in y if c]
(जहाँ e
और c
x
संदर्भ में अभिव्यक्तियाँ हैं) list(filter(lambda x: c, map(lambda x: e, y)))
बराबर है list(filter(lambda x: c, map(lambda x: e, y)))
।
समान परिणाम प्रदान करने के बावजूद, इस तथ्य पर ध्यान दें कि पूर्व उदाहरण बाद वाले की तुलना में लगभग 2 गुना तेज है। जो लोग उत्सुक हैं, उनके लिए यह एक अच्छा कारण है।
ध्यान दें कि यह ... if ... else ...
सशर्त अभिव्यक्ति (कभी-कभी एक टर्नरी एक्सप्रेशन के रूप में जाना जाता है) से काफी भिन्न होता है जिसे आप सूची <expression>
के <expression>
भाग के लिए उपयोग कर सकते हैं। निम्नलिखित उदाहरण पर विचार करें:
[x if x % 2 == 0 else None for x in range(10)]
# Out: [0, None, 2, None, 4, None, 6, None, 8, None]
यहां सशर्त अभिव्यक्ति फ़िल्टर नहीं है, बल्कि सूची आइटम के लिए उपयोग किए जाने वाले मान का निर्धारण करने वाला ऑपरेटर है:
<value-if-condition-is-true> if <condition> else <value-if-condition-is-false>
यदि आप इसे अन्य ऑपरेटरों के साथ जोड़ते हैं तो यह और स्पष्ट हो जाता है:
[2 * (x if x % 2 == 0 else -1) + 1 for x in range(10)]
# Out: [1, -1, 5, -1, 9, -1, 13, -1, 17, -1]
यदि आप पायथन 2.7 का उपयोग कर रहे हैं, तो xrange
कई कारणों से range
से बेहतर हो सकता है जैसा कि xrange
प्रलेखन में वर्णित है।
[2 * (x if x % 2 == 0 else -1) + 1 for x in xrange(10)]
# Out: [1, -1, 5, -1, 9, -1, 13, -1, 17, -1]
उपरोक्त कोड इसके बराबर है:
numbers = []
for x in range(10):
if x % 2 == 0:
temp = x
else:
temp = -1
numbers.append(2 * temp + 1)
print(numbers)
# Out: [1, -1, 5, -1, 9, -1, 13, -1, 17, -1]
एक टर्नरी अभिव्यक्तियों को जोड़ सकते हैं और if
स्थितियां हैं। टर्नरी ऑपरेटर फ़िल्टर किए गए परिणाम पर काम करता है:
[x if x > 2 else '*' for x in range(10) if x % 2 == 0]
# Out: ['*', '*', 4, 6, 8]
वही केवल टर्नरी ऑपरेटर द्वारा प्राप्त नहीं किया जा सकता था:
[x if (x > 2 and x % 2 == 0) else '*' for x in range(10)]
# Out:['*', '*', '*', '*', 4, '*', 6, '*', 8, '*']
यह भी देखें: फिल्टर , जो अक्सर सशर्त सूची समझ के लिए एक पर्याप्त विकल्प प्रदान करते हैं।
नेस्टेड लूप्स के साथ सूची की समझ
सूची की समझ for
छोरों के for
नेस्टेड का उपयोग कर सकते हैं। आप किसी सूची समझ के भीतर लूप के लिए किसी भी संख्या में नेस्टेड कोड कर सकते हैं, और लूप के for
प्रत्येक में एक वैकल्पिक हो सकता है if
परीक्षण। ऐसा करते समय, निर्माणों के for
आदेश उसी तरह का होता है जब बयानों के for
नेस्टेड की श्रृंखला लिखते हैं। सूची समझ की सामान्य संरचना इस प्रकार है:
[ expression for target1 in iterable1 [if condition1]
for target2 in iterable2 [if condition2]...
for targetN in iterableN [if conditionN] ]
उदाहरण के लिए, निम्न कोड स्टेटमेंट के for
कई का उपयोग करते हुए सूचियों की सूची को समतल करता है:
data = [[1, 2], [3, 4], [5, 6]]
output = []
for each_list in data:
for element in each_list:
output.append(element)
print(output)
# Out: [1, 2, 3, 4, 5, 6]
निर्माणों के for
कई for
साथ एक सूची समझ के रूप में समान रूप से लिखा जा सकता है:
data = [[1, 2], [3, 4], [5, 6]]
output = [element for each_list in data for element in each_list]
print(output)
# Out: [1, 2, 3, 4, 5, 6]
विस्तारित रूप और सूची समझ दोनों में, बाहरी लूप (कथन के लिए) पहले आता है।
अधिक कॉम्पैक्ट होने के अलावा, नेस्टेड कॉम्प्रिहेंशन भी काफी तेज है।
In [1]: data = [[1,2],[3,4],[5,6]]
In [2]: def f():
...: output=[]
...: for each_list in data:
...: for element in each_list:
...: output.append(element)
...: return output
In [3]: timeit f()
1000000 loops, best of 3: 1.37 µs per loop
In [4]: timeit [inner for outer in data for inner in outer]
1000000 loops, best of 3: 632 ns per loop
फ़ंक्शन कॉल के लिए ओवरहेड लगभग 140ns है ।
इनलाइन if
रों इसी तरह नेस्टेड रहते हैं, और पहले के बाद किसी भी स्थिति में हो सकता है for
:
data = [[1], [2, 3], [4, 5]]
output = [element for each_list in data
if len(each_list) == 2
for element in each_list
if element != 5]
print(output)
# Out: [2, 3, 4]
पठनीयता के लिए, हालांकि, आपको पारंपरिक फॉर-लूप्स का उपयोग करने पर विचार करना चाहिए। यह विशेष रूप से सच है जब घोंसला बनाना 2 से अधिक स्तर गहरा है, और / या समझ का तर्क बहुत जटिल है। एकाधिक नेस्टेड लूप सूची की समझ में त्रुटि हो सकती है या यह अप्रत्याशित परिणाम देता है।
समझ को सूचीबद्ध करने के लिए फिल्टर और मानचित्र को फिर से बनाना
filter
या map
फ़ंक्शंस को अक्सर सूची समझ के द्वारा प्रतिस्थापित किया जाना चाहिए। Guido Van Rossum ने 2005 में एक खुले पत्र में इस कुएं का वर्णन किया है:
filter(P, S)
लगभग हमेशा स्पष्ट लिखा जाता है[x for x in S if P(x)]
, और इसका बहुत बड़ा लाभ यह है कि इसमें सबसे सामान्य उपयोगों की तुलना में विधेय शामिल हैं, जैसेx==42
, और परिभाषित करना इसके लिए एक लंबोदर को पाठक के लिए बहुत अधिक प्रयास की आवश्यकता होती है (साथ ही मेमना सूची बोध की तुलना में धीमा है)।map(F, S)
लिए और भी अधिक जो कि[F(x) for x in S]
बन जाता है। बेशक, कई मामलों में आप इसके बजाय जनरेटर अभिव्यक्ति का उपयोग करने में सक्षम होंगे।
कोड की निम्नलिखित पंक्तियों को "पायथोनिक नहीं " माना जाता है और कई अजगर लिंटर में त्रुटियों को बढ़ाएगा।
filter(lambda x: x % 2 == 0, range(10)) # even numbers < 10
map(lambda x: 2*x, range(10)) # multiply each number by two
reduce(lambda x,y: x+y, range(10)) # sum of all elements in list
पिछली बोली से हमने जो सीखा है, उसे लेते हुए, हम इन filter
और map
अभिव्यक्तियों को उनकी समकक्ष सूची समझ में तोड़ सकते हैं; प्रत्येक से लंबोदर कार्यों को हटाने - कोड को प्रक्रिया में अधिक पठनीय बनाते हैं।
# Filter:
# P(x) = x % 2 == 0
# S = range(10)
[x for x in range(10) if x % 2 == 0]
# Map
# F(x) = 2*x
# S = range(10)
[2*x for x in range(10)]
चैनिंग कार्यों से निपटने के दौरान पठनीयता और भी स्पष्ट हो जाती है। जहां पठनीयता के कारण, अगले के परिणामस्वरूप एक मानचित्र या फ़िल्टर फ़ंक्शन के परिणाम पारित किए जाने चाहिए; साधारण मामलों के साथ, इन्हें एकल सूची समझ के साथ बदला जा सकता है। इसके अलावा, हम आसानी से सूची से समझ सकते हैं कि हमारी प्रक्रिया का परिणाम क्या है, जहां जंजीर मानचित्र और फ़िल्टर प्रक्रिया के बारे में तर्क देते समय अधिक संज्ञानात्मक भार होता है।
# Map & Filter
filtered = filter(lambda x: x % 2 == 0, range(10))
results = map(lambda x: 2*x, filtered)
# List comprehension
results = [2*x for x in range(10) if x % 2 == 0]
Refactoring - त्वरित संदर्भ
नक्शा
map(F, S) == [F(x) for x in S]
फ़िल्टर
filter(P, S) == [x for x in S if P(x)]
जहाँ F
और P
फ़ंक्शंस हैं जो क्रमशः इनपुट वैल्यूज़ को बदलते हैं और एक bool
वापस करते हैं
नेस्टेड सूची की समझ
नेस्टेड लूप के साथ सूची समझ के विपरीत नेस्टेड लिस्ट कॉम्प्रिहेंशन, एक लिस्ट कॉम्प्रिहेंशन के भीतर लिस्ट कॉम्प्रिहेंशन हैं। प्रारंभिक अभिव्यक्ति किसी भी अनियंत्रित अभिव्यक्ति हो सकती है, जिसमें एक और सूची समझ भी शामिल है।
#List Comprehension with nested loop
[x + y for x in [1, 2, 3] for y in [3, 4, 5]]
#Out: [4, 5, 6, 5, 6, 7, 6, 7, 8]
#Nested List Comprehension
[[x + y for x in [1, 2, 3]] for y in [3, 4, 5]]
#Out: [[4, 5, 6], [5, 6, 7], [6, 7, 8]]
नेस्टेड उदाहरण के बराबर है
l = []
for y in [3, 4, 5]:
temp = []
for x in [1, 2, 3]:
temp.append(x + y)
l.append(temp)
एक उदाहरण जहां एक नेस्टेड कॉम्प्रिहेंशन का उपयोग मैट्रिक्स को स्थानांतरित करने के लिए किया जा सकता है।
matrix = [[1,2,3],
[4,5,6],
[7,8,9]]
[[row[i] for row in matrix] for i in range(len(matrix))]
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
छोरों के for
नेस्टेड की तरह, गहरी समझ को कैसे सीमित किया जा सकता है इसकी कोई सीमा नहीं है।
[[[i + j + k for k in 'cd'] for j in 'ab'] for i in '12']
# Out: [[['1ac', '1ad'], ['1bc', '1bd']], [['2ac', '2ad'], ['2bc', '2bd']]]
सूची बोध के भीतर दो या दो से अधिक सूची एक साथ दर्ज करें
सूची बोध के भीतर एक साथ दो से अधिक सूचियों को पुनरावृत्त करने के लिए , व्यक्ति zip()
उपयोग कर सकता है:
>>> list_1 = [1, 2, 3 , 4]
>>> list_2 = ['a', 'b', 'c', 'd']
>>> list_3 = ['6', '7', '8', '9']
# Two lists
>>> [(i, j) for i, j in zip(list_1, list_2)]
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
# Three lists
>>> [(i, j, k) for i, j, k in zip(list_1, list_2, list_3)]
[(1, 'a', '6'), (2, 'b', '7'), (3, 'c', '8'), (4, 'd', '9')]
# so on ...