About Python for the external evaluation order in generator expressions

When repeating the following generator expression

fun(i) for i in mylist if i not in setA.union(setB) 

is the setA.union method called at each iteration, or only once?

+4
source share
3 answers

Simple proof using the dis module:

 In [24]: def func(): ....: a=set([1,2,3]) ....: b=set([3,4,5]) ....: c=[i for i in xrange(10) if i in a.union(b)] ....: In [25]: dis.dis(func) 4 42 BUILD_LIST 0 45 LOAD_GLOBAL 1 (xrange) 48 LOAD_CONST 6 (10) 51 CALL_FUNCTION 1 54 GET_ITER #iterator returned from xrange >> 55 FOR_ITER 33 (to 91) #until the iterator is not exhausted 58 STORE_FAST 2 (i) 61 LOAD_FAST 2 (i) 64 LOAD_FAST 0 (a) 67 LOAD_ATTR 2 (union) 70 LOAD_FAST 1 (b) 73 CALL_FUNCTION 1 #union() is being called in each iteration 76 COMPARE_OP 6 (in) 79 POP_JUMP_IF_FALSE 55 82 LOAD_FAST 2 (i) 85 LIST_APPEND 2 88 JUMP_ABSOLUTE 55 #end of loop >> 91 STORE_FAST 3 (c) 94 LOAD_CONST 0 (None) 97 RETURN_VALUE 

So, for your example, it will be called in each iteration, i.e. len(mylist) times.

+3
source

yes, setA.union(setB) is called every iteration,

you must do this before the generator expression and store it in a variable

 setvalues = setA.union(setB) fun(i) for i in mylist if i not in setvalues 
+3
source

Another way to check it is to profile it. Borrowing an example from @AshwiniChaudhary, I ran it through cProfile

 >>> def func(): a=set([1,2,3]) b=set([3,4,5]) c=[i for i in xrange(10) if i in a.union(b)] >>> import cProfile >>> cProfile.run("func()") 13 function calls in 0.000 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.000 0.000 <pyshell#1045>:1(func) 1 0.000 0.000 0.000 0.000 <string>:1(<module>) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 10 0.000 0.000 0.000 0.000 {method 'union' of 'set' objects} 

It is clearly stated here that the union is called 10 times

+3
source

All Articles