सूची समझ बनाम लैम्ब्डा + फिल्टर


857

मुझे अपने आप को एक बुनियादी फ़िल्टरिंग आवश्यकता होने का पता चला: मेरे पास एक सूची है और मुझे इसे आइटम की एक विशेषता द्वारा फ़िल्टर करना होगा।

मेरा कोड इस तरह देखा:

my_list = [x for x in my_list if x.attribute == value]

लेकिन फिर मैंने सोचा, क्या इसे इस तरह लिखना बेहतर नहीं होगा?

my_list = filter(lambda x: x.attribute == value, my_list)

यह अधिक पठनीय है, और यदि प्रदर्शन के लिए जरूरत पड़ती है तो लैम्बडा को कुछ हासिल करने के लिए निकाला जा सकता है।

प्रश्न है: क्या दूसरे तरीके का उपयोग करने में कोई कोताही है? किसी भी प्रदर्शन अंतर? क्या मुझे पाइथोनिक वे ™ पूरी तरह से याद आ रहा है और इसे अभी तक दूसरे तरीके से करना चाहिए (जैसे कि लैम्बडा के बजाय आइटम का उपयोग करना)?


19
एक बेहतर उदाहरण एक ऐसा मामला होगा जहां आपके पास पहले से ही अपने नामित व्यक्ति के रूप में उपयोग करने के लिए एक अच्छी तरह से नामित फ़ंक्शन है। उस मामले में, मुझे लगता है कि बहुत अधिक लोग सहमत होंगे कि filterअधिक पठनीय था। आप एक सरल अभिव्यक्ति एक listcomp में के रूप में है, लेकिन एक लैम्ब्डा में लिपटे हो गया है इस्तेमाल किया जा सकता है कि जब (या इसी के बाहर का निर्माण partialया operatorकरने के लिए पारित करने के लिए काम करता है, आदि) filter, है कि जब listcomps जीतने के लिए।
अपराह्न

3
यह कहा जाना चाहिए कि पायथन 3 में, कम से कम, filterएक फिल्टर जनरेटर ऑब्जेक्ट एक सूची नहीं है।
मट्टियो फेरला

जवाबों:


588

यह अजीब है कि विभिन्न लोगों के लिए सुंदरता कितनी भिन्न होती है। मुझे सूची की समझ filter+ की तुलना में बहुत स्पष्ट है lambda, लेकिन जो भी आपको आसान लगे, उसका उपयोग करें।

दो चीजें हैं जो आपके उपयोग को धीमा कर सकती हैं filter

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

अन्य ओवरहेड जो लागू हो सकता है वह यह है कि लैम्ब्डा को एक स्कोपेड वैरिएबल ( value) तक पहुंचने के लिए मजबूर किया जा रहा है । यह एक स्थानीय चर का उपयोग करने की तुलना में धीमी है और पायथन में 2.x सूची समझ केवल स्थानीय चर तक पहुँचता है। यदि आप पायथन 3.x का उपयोग कर रहे हैं, तो सूची बोध एक अलग फ़ंक्शन में चलता है, इसलिए यह valueएक क्लोजर के माध्यम से भी पहुंच जाएगा और यह अंतर लागू नहीं होगा।

अन्य विकल्प पर विचार करने के लिए एक सूची समझ के बजाय एक जनरेटर का उपयोग करना है:

def filterbyvalue(seq, value):
   for el in seq:
       if el.attribute==value: yield el

फिर आपके मुख्य कोड में (जो कि पठनीयता वास्तव में मायने रखती है) आपने सूची समझ और फिल्टर दोनों को एक उम्मीद के साथ सार्थक फ़ंक्शन नाम से बदल दिया है।


68
जनरेटर के लिए +1। मेरे पास एक प्रस्तुति के लिए घर पर एक लिंक है जो दिखाता है कि अद्भुत जनरेटर कैसे हो सकते हैं। आप, साथ ही बदलकर एक जनरेटर अभिव्यक्ति के साथ सूची समझ की जगह ले सकता []करने के लिए ()। इसके अलावा, मैं मानता हूं कि सूची COMP अधिक सुंदर है।
वेन वर्नर

1
दरअसल, नहीं - फिल्टर तेज है। वैसे ही जैसे कुछ का उपयोग कर त्वरित मानक के एक जोड़े को चलाने stackoverflow.com/questions/5998245/...
skqr

2
@skqr केवल बेंचमार्क के लिए समयसीमा का उपयोग करने के लिए बेहतर है, लेकिन कृपया एक उदाहरण दें जहां आप filterपायथन बैकबैक फ़ंक्शन का उपयोग करके तेज़ हो।
डंकन

8
@ tnq177 जेनरेटर पर डेविड बेस्ली की प्रस्तुति - dabeaz.com/generators
वेन वर्नर

2
@ VictorSchröder हाँ, शायद मैं अस्पष्ट था। मैं जो कहना चाह रहा था, वह यह था कि मुख्य कोड में आपको बड़ी तस्वीर देखने में सक्षम होना चाहिए। छोटे सहायक फ़ंक्शन में आपको केवल उस एक फ़ंक्शन के बारे में परवाह करने की आवश्यकता होती है, जो बाहर चल रहा है, उसे अनदेखा किया जा सकता है।
डंकन १

237

यह पायथन में कुछ हद तक धार्मिक मुद्दा है। भले ही गुइडो को हटाने पर विचार कियाmapfilterreduce गया था , और पायथन 3 से , वहाँ एक बैकलैश की पर्याप्तता थी जो अंत में केवल reduceबिल्ट-इन से फंक्शनलबुलस्रेड में ले जाया गया था ।

व्यक्तिगत रूप से मुझे सूची समझने में आसानी होती है। यह अधिक स्पष्ट है कि अभिव्यक्ति से क्या हो रहा है [i for i in list if i.attribute == value]क्योंकि सभी व्यवहार सतह पर है फिल्टर फ़ंक्शन के अंदर नहीं।

मैं दो दृष्टिकोणों के बीच प्रदर्शन अंतर के बारे में बहुत अधिक चिंता नहीं करूंगा क्योंकि यह सीमांत है। मैं वास्तव में इसे केवल तभी अनुकूलित करूंगा जब यह आपके आवेदन में अड़चन साबित हो जाए जो कि संभावना नहीं है।

इसके अलावा जब से बीडीएफएलfilter भाषा से चला गया था , तब निश्चित रूप से स्वचालित रूप से सूची बोध को अधिक पायथोनिक बनाता है ;-)


1
गुइडो के इनपुट के लिंक के लिए धन्यवाद, अगर मेरे लिए और कुछ नहीं है तो इसका मतलब है कि मैं उन्हें किसी भी तरह का उपयोग नहीं करने की कोशिश करूंगा, ताकि मुझे आदत न पड़े, और मैं उस धर्म का समर्थन नहीं
बनूंगा

1
लेकिन कम सरल उपकरणों के साथ करने के लिए सबसे जटिल है! नक्शे और फिल्टर समझ के साथ बदलने के लिए तुच्छ हैं!
njzk2

8
पता नहीं कम पायथन 3 में पदावनत किया गया था। अंतर्दृष्टि के लिए धन्यवाद! कम () अभी भी वितरित कंप्यूटिंग में काफी सहायक है, जैसे कि PySpark। मुझे लगता है कि यह एक गलती थी ..
तगर

1
@ आप अभी भी कम उपयोग कर सकते हैं बस आपको इसे फंक्शंस से आयात करना होगा
icc97

69

चूँकि किसी भी गति का अंतर मिनीस्कुल होना तय है, चाहे फ़िल्टर का उपयोग करना हो या सूची की समझ, स्वाद के मामले में नीचे आता है। सामान्य तौर पर मैं समझ का उपयोग करने के लिए इच्छुक हूं (जो कि यहां अधिकांश अन्य उत्तरों से सहमत है), लेकिन एक मामला है जहां मैं पसंद करता हूं filter

एक बहुत ही लगातार उपयोग के मामले में कुछ चलने योग्य एक्स के मूल्यों को एक विधेय पी (एक्स) के अधीन खींच रहा है:

[x for x in X if P(x)]

लेकिन कभी-कभी आप कुछ फ़ंक्शन को पहले मानों पर लागू करना चाहते हैं:

[f(x) for x in X if P(f(x))]


एक विशिष्ट उदाहरण के रूप में, विचार करें

primes_cubed = [x*x*x for x in range(1000) if prime(x)]

मुझे लगता है कि यह प्रयोग करने से थोड़ा बेहतर है filter। लेकिन अब विचार करें

prime_cubes = [x*x*x for x in range(1000) if prime(x*x*x)]

इस मामले में हम filterगणना के बाद के मूल्य के खिलाफ चाहते हैं । दो बार घन की गणना करने के मुद्दे के अलावा (अधिक महंगी गणना की कल्पना), दो बार अभिव्यक्ति लिखने का मुद्दा है, DRY सौंदर्यशास्त्र का उल्लंघन । इस मामले में मैं उपयोग करने के लिए उपयुक्त होगा

prime_cubes = filter(prime, [x*x*x for x in range(1000)])

7
क्या आप किसी अन्य सूची समझ के माध्यम से प्राइम का उपयोग करने पर विचार नहीं करेंगे? जैसे[prime(i) for i in [x**3 for x in range(1000)]]
viki.omega9

20
x*x*xअभाज्य संख्या, नहीं किया जा सकता के रूप में यह है x^2और xएक कारक के रूप में, उदाहरण के लिए वास्तव में एक गणितीय तरह से मतलब नहीं है, लेकिन शायद यह अभी भी helpul है। (हो सकता है कि हम कुछ बेहतर पा सकें।)
ज़ेल्फिर कल्टस्टाहल

3
ध्यान दें कि यदि हम मेमोरी नहीं खाना चाहते हैं तो हम अंतिम उदाहरण के बजाय एक जनरेटर अभिव्यक्ति का उपयोग कर सकते हैं:prime_cubes = filter(prime, (x*x*x for x in range(1000)))
मतीन उलहाक

4
@MateenUlhaq यह prime_cubes = [1]मेमोरी और सीपीयू साइकिल दोनों को बचाने के लिए अनुकूलित किया जा सकता है ;-)
डेनिस क्रुपेनिक

7
@ डेनिसकृपेनिक या यों कहें,[]
मतीन उल्हाक

29

हालांकि filter"तेज़ तरीका" हो सकता है, "पायथोनिक तरीका" ऐसी चीजों के बारे में परवाह नहीं करेगा जब तक कि प्रदर्शन बिल्कुल महत्वपूर्ण नहीं है (जिस स्थिति में आप पायथन का उपयोग नहीं करेंगे!)।


9
अक्सर देखे जाने वाले तर्क पर देर से टिप्पणी: कभी-कभी 10 के बजाय 5 घंटे में एक विश्लेषण चलाने का फर्क पड़ता है, और यदि एक घंटे के अजगर कोड को अनुकूलित करके प्राप्त किया जा सकता है, तो यह इसके लायक हो सकता है (विशेषकर यदि एक है) अजगर के साथ सहज और तेज भाषाओं के साथ नहीं)।
BLI

लेकिन अधिक महत्वपूर्ण यह है कि स्रोत कोड हमें पढ़ने और समझने की कोशिश में कितना धीमा कर देता है!
thoni56

20

मैंने सोचा था कि मैं इसे केवल पायथन 3 में जोड़ूंगा, फ़िल्टर () वास्तव में एक इट्रेटर ऑब्जेक्ट है, इसलिए आपको फ़िल्टर की गई सूची बनाने के लिए अपनी फ़िल्टर विधि कॉल को सूची () में पास करना होगा। तो अजगर 2 में:

lst_a = range(25) #arbitrary list
lst_b = [num for num in lst_a if num % 2 == 0]
lst_c = filter(lambda num: num % 2 == 0, lst_a)

सूचियों b और c में समान मान हैं, और लगभग उसी समय पूरा हो गया था जब फ़िल्टर () z में x के लिए x [x] के बराबर था। हालाँकि, 3 में, यह वही कोड एक फ़िल्टर ऑब्जेक्ट वाली सूची c छोड़ देगा, फ़िल्टर की गई सूची नहीं। 3 में समान मान उत्पन्न करने के लिए:

lst_a = range(25) #arbitrary list
lst_b = [num for num in lst_a if num % 2 == 0]
lst_c = list(filter(lambda num: num %2 == 0, lst_a))

समस्या यह है कि सूची () तर्क के रूप में एक पुनरावृत्ति लेता है, और उस तर्क से एक नई सूची बनाता है। इसका परिणाम यह है कि अजगर 3 में इस तरह से फिल्टर का उपयोग करते हुए दो बार तक ले जाता है जब तक [x के लिए x में y यदि z] विधि है क्योंकि आपको फ़िल्टर () और साथ ही मूल सूची से आउटपुट पर पुनरावृति करना होगा।


13

एक महत्वपूर्ण अंतर यह है कि सूची की समझ वापस आ जाएगी listजब फ़िल्टर वापस आ जाएगाfilter , जिसे आप एक की तरह जोड़ तोड़ नहीं कर सकते list(यानी: lenउस पर कॉल करें , जो वापसी के साथ काम नहीं करता है filter)।

मेरे स्वयं के सीखने ने मुझे कुछ इसी तरह के मुद्दे पर लाया।

कहा जा रहा है, अगर वहाँ एक तरीका है जिसके परिणामस्वरूप है list से एक है filter, आप की तरह एक बिट .नेट में जब आप करते हैंlst.Where(i => i.something()).ToList() , मैं इसे जानने के लिए उत्सुक हूँ।

संपादित करें: यह पायथन 3 के लिए मामला है, 2 नहीं (टिप्पणियों में चर्चा देखें)।


4
फ़िल्टर एक सूची देता है और हम इस पर लेन का उपयोग कर सकते हैं। कम से कम मेरे पाइथन 2.7.6 में।
तेरुवेंकदम

7
यह अजगर 3 में मामला नहीं है a = [1, 2, 3, 4, 5, 6, 7, 8] f = filter(lambda x: x % 2 == 0, a) lc = [i for i in a if i % 2 == 0] >>> type(f) <class 'filter'> >>> type(lc) <class 'list'>
अद्यांक

3
"यदि परिणामी सूची होने का कोई तरीका है ... मैं इसे जानने के लिए उत्सुक हूं"। बस फोन list()परिणाम पर: list(filter(my_func, my_iterable))। और निश्चित रूप से आप के listसाथ बदल सकते हैं set, या tuple, या कुछ और जो एक पुनरावृत्ति लेता है। लेकिन कार्यात्मक प्रोग्रामर के अलावा किसी अन्य के लिए, मामला filterस्पष्ट रूप से रूपांतरण करने के बजाय सूची समझ का उपयोग करने के लिए और भी मजबूत है list
स्टीव जेसोप

10

मुझे दूसरा रास्ता अधिक पठनीय लगता है। यह आपको बताता है कि इरादा क्या है: सूची को फ़िल्टर करें।
पुनश्च: एक चर नाम के रूप में 'सूची' का उपयोग न करें


7

आम तौर पर filterअगर बिल्टिन फ़ंक्शन का उपयोग किया जाता है तो पर थोड़ा तेज़ होता है।

मुझे उम्मीद है कि सूची आपके मामले में थोड़ी तेज होगी


python -m timeit 'फ़िल्टर (लैम्ब्डा x: x में [1,2,3,4,5], रेंज (10000000))' 10 छोरों, 3 का सर्वश्रेष्ठ: 1.44 सेकंड प्रति लूप अजगर -m timeit 'x के लिए x रेंज में (10000000) अगर x में [1,2,3,4,5]] '10 लूप्स, बेस्ट ऑफ़ 3: 860 मिसेक प्रति लूप वास्तव में नहीं है ?!
जिआसुदौ

@sepdau, लैम्ब्डा फंक्शन बिलिन नहीं हैं। पिछले 4 वर्षों में सूची की समझ में सुधार हुआ है - अब यह अंतर बिलिन के कार्यों के साथ भी नगण्य है
जॉन ला रोय

7

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

आपके उदाहरण में, परिभाषा के अनुसार, सूची समझ से फिल्टर का उपयोग करना बेहतर है। हालाँकि, यदि आप चाहते हैं कि सूची तत्वों से अन्य_अभिनय बोलें, आपके उदाहरण में एक नई सूची के रूप में पुनर्प्राप्त किया जाना है, तो आप सूची समझ का उपयोग कर सकते हैं।

return [item.other_attribute for item in my_list if item.attribute==value]

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


2
मुझे डाउन वोटिंग का कारण जानकर खुशी होगी, ताकि भविष्य में मैं इसे फिर से कहीं न दोहराऊं।
तेरुवेंकदम

फ़िल्टर और सूची समझ की परिभाषा आवश्यक नहीं थी, क्योंकि उनके अर्थ पर बहस नहीं की जा रही थी। यह कि सूची की समझ का उपयोग केवल "नई" सूचियों के लिए किया जाना चाहिए, लेकिन इसके लिए तर्क नहीं दिया गया है।
अग्स

मैंने यह कहने के लिए परिभाषा का उपयोग किया कि फ़िल्टर आपको उन्हीं तत्वों के साथ सूची देता है जो किसी मामले के लिए सत्य हैं, लेकिन सूची की समझ के साथ हम तत्वों को संशोधित कर सकते हैं, जैसे int को str में बदलना। लेकिन बिंदु लिया :-)
thiruvenkadam

4

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

इस मामले में मैं एक फ़ाइल पढ़ रहा हूं, खाली लाइनों को अलग करना, लाइनों पर टिप्पणी करना और एक लाइन पर एक टिप्पणी के बाद कुछ भी:

# Throw out blank lines and comments
with open('file.txt', 'r') as lines:        
    # From the inside out:
    #    [s.partition('#')[0].strip() for s in lines]... Throws out comments
    #   filter(lambda x: x!= '', [s.part... Filters out blank lines
    #  y for y in filter... Converts filter object to list
    file_contents = [y for y in filter(lambda x: x != '', [s.partition('#')[0].strip() for s in lines])]

यह वास्तव में बहुत कम कोड में बहुत कुछ हासिल करता है। मुझे लगता है कि आसानी से समझने और पठनीयता को समझने के लिए एक पंक्ति में थोड़ा बहुत तर्क हो सकता है।
ज़ेलफिर कलस्टहल

आप इसे इस प्रकार लिख सकते हैंfile_contents = list(filter(None, (s.partition('#')[0].strip() for s in lines)))
स्टीव जेसप

4

स्वीकृत जवाब के अलावा, एक कोने का मामला है जब आपको सूची समझ के बजाय फ़िल्टर का उपयोग करना चाहिए। यदि सूची उपलब्ध नहीं है, तो आप सीधे इसे सूची बोध के साथ संसाधित नहीं कर सकते। एक वास्तविक दुनिया उदाहरण है यदि आप pyodbcडेटाबेस से परिणाम पढ़ने के लिए उपयोग करते हैं। fetchAll()से परिणाम cursorएक unhashable सूची है। इस स्थिति में, लौटे परिणामों पर सीधे हेरफेर करने के लिए, फ़िल्टर का उपयोग किया जाना चाहिए:

cursor.execute("SELECT * FROM TABLE1;")
data_from_db = cursor.fetchall()
processed_data = filter(lambda s: 'abc' in s.field1 or s.StartTime >= start_date_time, data_from_db) 

यदि आप सूची बोध का उपयोग करते हैं तो आपको त्रुटि मिलेगी:

TypeError: अस्वाभाविक प्रकार: 'सूची'


1
सभी सूचियाँ अस्वाभाविक हैं, >>> hash(list()) # TypeError: unhashable type: 'list'यह ठीक काम करती है:processed_data = [s for s in data_from_db if 'abc' in s.field1 or s.StartTime >= start_date_time]
थॉमस

"यदि सूची उपलब्ध नहीं है, तो आप इसे सूची बोध के साथ सीधे संसाधित नहीं कर सकते।" यह सच नहीं है, और सभी सूचियाँ वैसे भी उपलब्ध नहीं हैं।
juanpa.arrivillaga

3

यह मुझे कुछ समय से परिचित पाने के लिए ले लिया higher order functions filterऔर map। इसलिए मुझे उनकी आदत हो गई और मुझे वास्तव में पसंद आया filterक्योंकि यह स्पष्ट था कि जो कुछ भी सत्य है उसे रखकर यह फ़िल्टर किया गया है और मुझे अच्छा लगा है कि मुझे कुछ functional programmingशर्तें पता थीं ।

तब मैंने इस अंश (धाराप्रवाह पुस्तक) को पढ़ा:

पायथन 3 में मानचित्र और फ़िल्टर फ़ंक्शंस अभी भी बने हुए हैं, लेकिन चूंकि सूची बोध और जनरेटर एक्सो प्रेस की शुरुआत के बाद, वे उतने महत्वपूर्ण नहीं हैं। एक सूचीबैंक या एक जीनएक्सपी संयुक्त रूप से मानचित्र और फ़िल्टर का काम करता है, लेकिन अधिक पठनीय है।

और अब मुझे लगता है, क्यों filter/ mapअगर आप इसे पहले से ही व्यापक रूप से फैले हुए मुहावरों जैसे सूची बोध के साथ प्राप्त कर सकते हैं / की अवधारणा से परेशान हैं । इसके अलावा mapsऔर filtersप्रकार के कार्य हैं। इस मामले में मैं उपयोग करना पसंद करता हूंAnonymous functions लंबोदा ।

अंत में, बस इसे जांचने के लिए, मैंने दोनों विधियों ( mapऔर listComp) को समयबद्ध किया है और मुझे ऐसा कोई प्रासंगिक गति अंतर नहीं मिला है जो इसके बारे में तर्क देने को उचित ठहराए।

from timeit import Timer

timeMap = Timer(lambda: list(map(lambda x: x*x, range(10**7))))
print(timeMap.timeit(number=100))

timeListComp = Timer(lambda:[(lambda x: x*x) for x in range(10**7)])
print(timeListComp.timeit(number=100))

#Map:                 166.95695265199174
#List Comprehension   177.97208347299602

0

पायथन 3 पर उत्सुकता से, मुझे सूची बोध की तुलना में तेजी से प्रदर्शन करते हुए दिखाई देता है।

मैंने हमेशा सोचा था कि सूची की समझ अधिक प्रदर्शन वाली होगी। कुछ इस तरह से: [नाम के लिए brand_names_db में नाम अगर कोई नहीं है] तो उत्पन्न बायटेकोड थोड़ा बेहतर है।

>>> def f1(seq):
...     return list(filter(None, seq))
>>> def f2(seq):
...     return [i for i in seq if i is not None]
>>> disassemble(f1.__code__)
2         0 LOAD_GLOBAL              0 (list)
          2 LOAD_GLOBAL              1 (filter)
          4 LOAD_CONST               0 (None)
          6 LOAD_FAST                0 (seq)
          8 CALL_FUNCTION            2
         10 CALL_FUNCTION            1
         12 RETURN_VALUE
>>> disassemble(f2.__code__)
2           0 LOAD_CONST               1 (<code object <listcomp> at 0x10cfcaa50, file "<stdin>", line 2>)
          2 LOAD_CONST               2 ('f2.<locals>.<listcomp>')
          4 MAKE_FUNCTION            0
          6 LOAD_FAST                0 (seq)
          8 GET_ITER
         10 CALL_FUNCTION            1
         12 RETURN_VALUE

लेकिन वे वास्तव में धीमी हैं:

   >>> timeit(stmt="f1(range(1000))", setup="from __main__ import f1,f2")
   21.177661532000116
   >>> timeit(stmt="f2(range(1000))", setup="from __main__ import f1,f2")
   42.233950221000214

8
अवैध तुलना । सबसे पहले, आप एक लंबो फ़ंक्शन को फ़िल्टर संस्करण में नहीं दे रहे हैं, जिससे यह पहचान फ़ंक्शन के लिए डिफ़ॉल्ट हो जाता है। जब परिभाषित करने if not Noneसूची समझ में आप कर रहे हैं एक लैम्ब्डा समारोह को परिभाषित (नोटिस MAKE_FUNCTIONबयान)। दूसरे, परिणाम अलग-अलग हैं, क्योंकि सूची समझ संस्करण केवल Noneमान को हटा देगा , जबकि फ़िल्टर संस्करण सभी "गलत" मानों को हटा देगा। यह कहने के बाद, माइक्रोबेनमार्किंग का पूरा उद्देश्य बेकार है। वे एक मिलियन पुनरावृत्तियों, 1k आइटम हैं! अंतर नगण्य है
विक्टर श्रोडर

-7

मेरा स्वीकार कर लेना

def filter_list(list, key, value, limit=None):
    return [i for i in list if i[key] == value][:limit]

3
iकभी नहीं कहा गया था dict, और इसके लिए कोई आवश्यकता नहीं है limit। इसके अलावा, ओपी ने जो सुझाव दिया है, उससे यह कैसे अलग है और यह सवाल का जवाब कैसे देता है?
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.