Python Forum

Full Version: List comprehension
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Please explain why this doesn't work
seq=[1,2,3]
def a(): return x+2
x=[a() for x in seq]
I thought a list comprehension create a new local scope for the expression itself, and when we use a(), x is searched by the LEGB rule and can find the x in the enclosing scope, am i correct ?
Following is friendly banter. No offence intended.

These repeated questions reminded me 'sketch' from Three Men in a Boat by Jerome K Jerome.

One can read whole episode here, but for immediate usage I provide prescription:

Quote:1 lb. beefsteak, with
1 pt. bitter beer
every 6 hours.
1 ten-mile walk every morning.
1 bed at 11 sharp every night.
And don’t stuff up your head with things you don’t understand.

As for question: it's always good practice to use functions with parameters.

>>> seq = [1, 2, 3]                                                        
>>> def a(x): return x + 2                                                 
>>> lst = [a(num) for num in seq]                                          
>>> lst                                                                    
[3, 4, 5]
(Jul-17-2019, 02:46 AM)Uchikago Wrote: [ -> ]Please explain why this doesn't work
seq=[1,2,3]
def a(): return x+2
x=[a() for x in seq]
Sorry but this code is complete nonsense and that´s the reason it´s not working.
You definitely should watch some tutorial, e.g. this one here.
Not sure, is this question very simple, or very tricky...So, lets do some examples here.
First of all, lets start with the following example:

def a():
    return x + 2

for x in range(10):
    print(a(), globals().get('x'))
Output:
2 0 3 1 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9
Everthing works as expected: for loop creates x-values in the global scope, and the variable x is visible from the a()-function.

List comprehensions are functions too. To show this, lets consider the following bytecode, e.g.
import dis
dis.dis("[x for x in range(5, dont_execute_me='I am in op-code')]")
Output:
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x7f8a0d898ed0, file "<dis>", line 1>) 3 LOAD_CONST 1 ('<listcomp>') 6 MAKE_FUNCTION 0 9 LOAD_NAME 0 (range) 12 LOAD_CONST 2 (5) 15 LOAD_CONST 3 ('dont_execute_me') 18 LOAD_CONST 4 ('I am in op-code') 21 CALL_FUNCTION 257 (1 positional, 1 keyword pair) 24 GET_ITER 25 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 28 RETURN_VALUE
Line #25 executes list comprehension-function; line #21 creates range;

How to make it works...

We just need to declare something like this: [a() for x in range(5); global x]; but this isn't allowed by Python syntax.

Nevertheless, we can do some injection, e.g.

[(globals().update({"x":x}),  a())[-1] for x in range(3)]
Output:
[2, 3, 4]
Everything works fine! This is just for fun, don't do this in any valuable code.