function inside list comprehension - is it evaluat

2019-04-03 08:52发布

问题:

This question already has an answer here:

  • Python: Is the split function evaluated multiple times in a list comprehension? 3 answers

Which one's a better way of doing list comprehension in python (in terms of computation time & cpu cycles). In example (1) is the value f(r) evaluated in each iteration or is it evaluated once and cached ?

  1. y = [x*f(r) for x in xlist]

  2. c = f(r)

    y = [x*c for x in xlist]

where

def f(r):
    ... some arbitrary function ...

回答1:

I would probably choose the latter because the Python compiler doesn't know if the function has side-effects so it is called for each element.



回答2:

It evaluates for every iteration. Look at this:

>>> def f():
...     print("func")
... 
>>> [f() for i in range(4)]
func
func
func
func
[None, None, None, None]

As you say, if f() has no side effects, storing the return value on a variable and using that variable instead is a lot faster solution.



回答3:

Here is an easy way to find out:

>>> def f():
...     print "called"
...     return 1
...
>>> [1+f() for x in xrange(5)]
called
called
called
called
called
[2, 2, 2, 2, 2]

so yes, if the function is going to be the same each time then it is better to call it once outside the list comprehension.



回答4:

The function f will be called for every element.



回答5:

It is very complex for the compiler/interpreter to determine that the function need not to be called many times. It is then very probable that the function is called many times. Thus, using the second solution is always the best solution.



回答6:

Functions have a non-trivial execution time compared to a name lookup, and caching the value is considered acceptable if the function is called many times and the same value is expected each time.



回答7:

Python is probably free to do it once or many times, I'm not sure I would rely on any observed behavior. It might change in the next version.

If it's important to you to make sure the function is only called once, call it yourself and save the results.