2015-07-15 8 views
5

उदाहरण के रूप में नीचे का उपयोग करके, हम देख सकते हैं कि x.giveMyNum() को 4 गुना - 3 बार कहा जाएगा, ताकि मेरे नंबर के मूल्य की जांच हो और एक बार सूची को वापस करने के लिए बनाया जा सके। आप शायद इसे केवल 3 बार बुलाएंगे, क्योंकि यह एक शुद्ध कार्य है और इसका मूल्य नहीं बदलेगा।सूची समझ में एकाधिक कॉल को रोकना

सूची बूझ संस्करण:

class test(object): 
    def __init__(self,myNum): 
     self.myNum=myNum 
    def giveMyNum(self): 
     print "giving" 
     return self.myNum 
q=[test(x) for x in range(3)] 
print [x.giveMyNum() for x in q if x.giveMyNum()>1] 

मैं जानता हूँ कि आप इस तरह से कुछ कर सकते हैं इसे ठीक करने के:

ret=[] 
for x in q: 
    k=x.giveMyNum() 
    if k>1: 
     ret.append(k) 

लेकिन वहाँ एक सूची समझ में अतिरिक्त कॉल को रोकने के लिए एक रास्ता है?

मुझे मध्यवर्ती मूल्य रखने की आवश्यकता नहीं है।

उत्तर

3

आप इसे जनरेटर के साथ जोड़ सकते हैं लेकिन मैं नियमित लूप के साथ रहूंगा।

print([n for n in (x.giveMyNum() for x in q) if n > 1 ]) 

आप कार्यात्मक कोड को पसंद करते हैं आप मैप कर सकते या itertools.imap को Python2 साथ:

print([n for n in map(test.giveMyNum, q) if n > 1 ]) 

को Python2 और IMAP का उपयोग कर जनरल exp की तुलना में तेजी है:

In [8]: q = [test(x) for x in range(10000)] 

In [9]: timeit [ n for n in imap(test.giveMyNum, q) if n > 1] 
1000 loops, best of 3: 1.94 ms per loop 

In [10]: timeit [n for n in (x.giveMyNum() for x in q) if n > 1 ] 
100 loops, best of 3: 2.56 ms per loop 

नक्शा भी तेजी से उपयोग कर रहा है पायथन 3:

In [2]: timeit [ n for n in map(test.giveMyNum, q) if n > 1] 
100 loops, best of 3: 2.23 ms per loop 

In [3]: timeit [n for n in (x.giveMyNum() for x in q) if n > 1 ] 
100 loops, best of 3: 2.93 ms per loop 
,210

नियमित पाश के लिए समय और विधि बुला:

In [8]: timeit [x.giveMyNum() for x in q if x.giveMyNum()>1] 
100 loops, best of 3: 3.59 ms per loop 

In [9]: %%timeit 
ret=[] 
for x in q: 
    k=x.giveMyNum() 
    if k>1: 
     ret.append(k) 
    ...: 
100 loops, best of 3: 2.67 ms per loop 

python3:

In [2]: %%timeit 
ret=[] 
for x in q: 
    k=x.giveMyNum() 
    if k>1: 
     ret.append(k) 
    ...: 
100 loops, best of 3: 2.84 ms per loop 

In [3]: timeit [x.giveMyNum() for x in q if x.giveMyNum()>1] 

100 loops, best of 3: 4.08 ms per loop 
+0

मुझे कार्यात्मक कोड पसंद है। यह बहुत पठनीय है। – Carbon

+0

@ProbablyAStupidQuestion, तो आपको 'फ़िल्टर (लैम्ब्डा एन: एन> 1, मानचित्र (test.giveMyNum, q)) हो सकता है)); –

+0

यह वास्तव में अच्छा है! मुझे दुखद फिल्टर Python3 में itertools में स्थानांतरित किया जा रहा है। – Carbon

3

यह संभव है, लेकिन बहुत पठनीय नहीं है ...

print [y for y in (x.giveMyNum() for x in q) if y > 1] 

इसलिए जब तक giveMyNum() धीमी है या शुद्ध नहीं मैं इसे टालना चाहूंगा।

+0

यह कमाल है - जनरेटर समझ! यह वास्तव में चालाक है। मैं पूछ रहा था क्योंकि मेरे पास धीमी शुद्ध कार्य के साथ मामला है और यह इसे एक अच्छे तरीके से हल करता है। – Carbon

संबंधित मुद्दे