Using the below as an example, we can see x.giveMyNum() will be called 4 times - 3 times to check the value of myNum and once to construct the list to return. You'd probably want it to be called only 3 times, as it's a pure function and its value won't change.
List Comprehension Version:
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]
I know you can do something like this to fix it:
ret=[]
for x in q:
k=x.giveMyNum()
if k>1:
ret.append(k)
but is there a way to prevent the extra call in a list comprehension?
I don't need to keep the intermediate value.
You can combine it with a generator but I would stick with a regular loop.
print([n for n in (x.giveMyNum() for x in q) if n > 1 ])
If you like functional code you could map or itertools.imap
with python2:
print([n for n in map(test.giveMyNum, q) if n > 1 ])
Using python2 and imap is faster than the gen 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
map is also faster using 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
The timing for the regular loop and calling the method:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With