2015-07-15 5 views
5

Aşağıdaki örnek kullanılarak, xNiveMyNum() öğesinin myNum değerini kontrol etmek için 4 kez ve bir kez de geri dönmek için liste oluşturmak için 4 kez çağrılabileceğini görebiliriz. Büyük bir işlev olduğu ve değerinin değişmeyeceği için muhtemelen sadece 3 kez çağrılmasını istersiniz.Liste anlaşmasında birden çok çağrının engellenmesi

Liste Anlama Versiyon:

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] 

Ben bunu düzeltmek için böyle bir şey yapabileceğini biliyorum:

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

ancak liste anlama ekstra aramayı önlemek için bir yol var?

Ara değerini tutmak zorunda değilim.

cevap

3

Bunu bir jeneratörle birleştirebilirsiniz, ancak düzenli bir döngü ile yapışırdım. python2 ile

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

Eğer fonksiyonel kodu seviyorsanız harita olabilir veya itertools.imap:

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

python2 ve imap kullanarak gen exp daha hızlıdır:

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 

harita kullanarak da daha hızlıdır python3:

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

düzenli döngü zamanlama ve yöntemini çağırarak:

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

İşlevsel kodu severim. Bu çok okunabilir. – Carbon

+0

@ProbablyAStupidQuestion, daha sonra filtre (lambda n: n> 1, harita (test.giveMyNum, q))) ';) –

+0

gerçekten hoşunuza gidebilir! Ben üzgün filtre Python3 itertools içine taşınmaktadır. – Carbon

3

Çok okunabilir mümkün değil ama ...

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

yüzden giveMyNum() yavaş olmadıkça ya da saf değil, bundan kaçarım.

+0

Bu harika - bir jeneratör anlayışı! Bu gerçekten zekice. Ben soruyordum çünkü yavaş bir saf işlevi olan bir durumum var ve bu onu güzel bir şekilde çözüyor. – Carbon