List comprehension with repeated computation

2019-06-24 05:41发布

问题:

I am currently playing about with Project Euler problem 53 in Python. The solution is trivially simple but involved the following list comprehension:

[scipy.misc.comb(n, r, exact=True)
 for n in range(1,maxn+1)
 for r in range(0,n+1)
 if scipy.misc.comb(n, r, exact=True) > threshold]

My concern is though that the scipy.misc.comb() function would be called twice per iteration. Is there any way of replacing one or other occurrence of it with some sort of reference; alternatively is the interpreter smart enough to realise that the two instances will evaluate to the same thing?

回答1:

You can put the scipy.misc.comb() function into a generator expression:

[comb for comb in 
    (scipy.misc.comb(n, r, exact=True) 
     for n in range(1,maxn+1) for r in range(0,n+1))
 if comb > threshold]

and it'll be calculated just once per iteration over the generator.

Putting the generator expression into a separate variable may make this clearer:

calculated = (scipy.misc.comb(n, r, exact=True) 
              for n in range(1,maxn+1) for r in range(0,n+1))
[comb for comb in calculated if comb > threshold]

See this as a conveyor belt; the calculated generator is only producing its output as the list comprehension iterates over it.