Why do these two functions have the same bytecode when disassembled under dis.dis?Python: analyze a list comprehension with disIs it possible to call a function from within a list comprehension without the overhead of calling the function?Speed comparison with Project Euler: C vs Python vs Erlang vs HaskellWhy do some functions have underscores “__” before and after the function name?Is list join really faster than string concatenation in python?Why is my 'xmap' function not any faster than built-in 'map'?Are list-comprehensions and functional functions faster than “for loops”?Why doesn't Python optimize away temporary variables?Python: why is one generator faster than other with `yield` inside?Why is this loop faster than a dictionary comprehension for creating a dictionary?How do I get LOAD_CLASSDEREF instruction after dis.dis?

Boot Windows from SAN

How much does Commander Data weigh?

"fF" letter combination seems to be typeset strangely or incorrectly

How to check whether a sublist exist in a huge database lists in a fast way?

What does "rel" in `mathrel` and `stackrel` stands for?

Where can/should I, as a high schooler, publish a paper regarding the derivation of a formula?

If someone uses the Command spell and says "drop", what happens?

Nothing like a good ol' game of ModTen

Why doesn't 'd /= d' throw a division by zero exception?

Evaluated vs. unevaluated Association

The Wires Underground

Are the players on the same team as the DM?

How were medieval castles built in swamps or marshes without draining them?

When calculating a force, why do I get different result when I try to calculate via torque vs via sum of forces at an axis?

Can $! cause race conditions when used in scripts running in parallel?

Why is the UK so keen to remove the "backstop" when their leadership seems to think that no border will be needed in Northern Ireland?

Another solution to create a set with two conditions

What are the occurences of total war in the Native Americans?

"There were either twelve sexes or none."

What is the right path to be followed on Chess.com for learning Chess?

How to gently end involvement with an online community?

How many birds in the bush?

How can I download a file through 2 SSH connections?

Redacting URLs as an email-phishing preventative?



Why do these two functions have the same bytecode when disassembled under dis.dis?


Python: analyze a list comprehension with disIs it possible to call a function from within a list comprehension without the overhead of calling the function?Speed comparison with Project Euler: C vs Python vs Erlang vs HaskellWhy do some functions have underscores “__” before and after the function name?Is list join really faster than string concatenation in python?Why is my 'xmap' function not any faster than built-in 'map'?Are list-comprehensions and functional functions faster than “for loops”?Why doesn't Python optimize away temporary variables?Python: why is one generator faster than other with `yield` inside?Why is this loop faster than a dictionary comprehension for creating a dictionary?How do I get LOAD_CLASSDEREF instruction after dis.dis?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








6















What follows is four functions that have the same output, but either written with a list comprehension or a tight loop, and a function call to vs an inline condition.



Interestingly, a and b have the same bytecode when disassembled, however b is much faster than a.



Moreover, d, which uses a tight loop with no function call, is faster than a which uses a list comprehension with a function call.



Why do functions a and b have the same bytecode, and why does b perform much better than a given the same bytecode?



import dis

def my_filter(n):
return n < 5

def a():
# list comprehension with function call
return [i for i in range(10) if my_filter(i)]

def b():
# list comprehension without function call
return [i for i in range(10) if i < 5]

def c():
# tight loop with function call
values = []
for i in range(10):
if my_filter(i):
values.append(i)
return values

def d():
# tight loop without function call
values = []
for i in range(10):
if i < 5:
values.append(i)
return values

assert a() == b() == c() == d()

import sys
>>> sys.version_info[:]
(3, 6, 5, 'final', 0)

# list comprehension with function call
>>> dis.dis(a)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

# list comprehension without function call
>>> dis.dis(b)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBB64270, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

# a and b have the same byte code?
# Why doesn't a have a LOAD_GLOBAL (my_filter) and CALL_FUNCTION?
# c below has both of these

# tight loop with function call
>>> dis.dis(c)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (values)

3 4 SETUP_LOOP 34 (to 40)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 1 (10)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 22 (to 38)
16 STORE_FAST 1 (i)

4 18 LOAD_GLOBAL 1 (my_filter)
20 LOAD_FAST 1 (i)
22 CALL_FUNCTION 1
24 POP_JUMP_IF_FALSE 14

5 26 LOAD_FAST 0 (values)
28 LOAD_ATTR 2 (append)
30 LOAD_FAST 1 (i)
32 CALL_FUNCTION 1
34 POP_TOP
36 JUMP_ABSOLUTE 14
>> 38 POP_BLOCK

6 >> 40 LOAD_FAST 0 (values)
42 RETURN_VALUE

# tight loop without function call
>>> dis.dis(d)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (values)

3 4 SETUP_LOOP 34 (to 40)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 1 (10)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 22 (to 38)
16 STORE_FAST 1 (i)

4 18 LOAD_FAST 1 (i)
20 LOAD_CONST 2 (5)
22 COMPARE_OP 0 (<)
24 POP_JUMP_IF_FALSE 14

5 26 LOAD_FAST 0 (values)
28 LOAD_ATTR 1 (append)
30 LOAD_FAST 1 (i)
32 CALL_FUNCTION 1
34 POP_TOP
36 JUMP_ABSOLUTE 14
>> 38 POP_BLOCK

6 >> 40 LOAD_FAST 0 (values)
42 RETURN_VALUE

import timeit

>>> timeit.timeit(a) # list comprehension with my_filter
1.2435139456834463
>>> timeit.timeit(b) # list comprehension without my_filter
0.6717423789164627
>>> timeit.timeit(c) # no list comprehension with my_filter
1.326850592144865
>>> timeit.timeit(d) # no list comprehension no my_filter
0.7743895521070954


Why do a and b have the same byte code when disassembled? I would have expected b to have better looking bytecode. Notably I would have thought that a would need a LOAD_GLOBAL ? (my_filter) and a CALL FUNCTION. For example, c is the same as a but without the list comprehension, and it uses these bytecodes these on addresses 18 and 22.



However, even with the same bytecode, b performs much better than a. What's going on here?



Even more interesting, d, which uses a tight loop but does not have the call to my_filter, is faster than b which uses the list comprehension but has the call to my_filter. It looks like the overhead of using a function outweighs the overhead of a tight loop.



My goal here is to try to figure out if I can factor out conditions of a list comprehension into a function to make the list comprehension easier to read.










share|improve this question





















  • 2





    What's your python version? In 3.7, it also disassembles the <listcomp> itself, which is of course quite different for your two functions.

    – georg
    8 hours ago











  • @georg I'm on Python 3.6.5

    – Matthew Moisen
    8 hours ago






  • 1





    The body of a list comprehension is compiled as if it were a nested function. Note the complete lack of any reference to my_filter() in a(), you're obviously not seeing everything in the disassembly.

    – jasonharper
    8 hours ago











  • @georg Got it. Would you like to make an answer? dis.dis(a.__code__.co_consts[1]) and dis.dis(b.__code__.co_consts[1]) shows the difference. If you could show what it looks like in 3.7 that would be great as well.

    – Matthew Moisen
    8 hours ago

















6















What follows is four functions that have the same output, but either written with a list comprehension or a tight loop, and a function call to vs an inline condition.



Interestingly, a and b have the same bytecode when disassembled, however b is much faster than a.



Moreover, d, which uses a tight loop with no function call, is faster than a which uses a list comprehension with a function call.



Why do functions a and b have the same bytecode, and why does b perform much better than a given the same bytecode?



import dis

def my_filter(n):
return n < 5

def a():
# list comprehension with function call
return [i for i in range(10) if my_filter(i)]

def b():
# list comprehension without function call
return [i for i in range(10) if i < 5]

def c():
# tight loop with function call
values = []
for i in range(10):
if my_filter(i):
values.append(i)
return values

def d():
# tight loop without function call
values = []
for i in range(10):
if i < 5:
values.append(i)
return values

assert a() == b() == c() == d()

import sys
>>> sys.version_info[:]
(3, 6, 5, 'final', 0)

# list comprehension with function call
>>> dis.dis(a)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

# list comprehension without function call
>>> dis.dis(b)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBB64270, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

# a and b have the same byte code?
# Why doesn't a have a LOAD_GLOBAL (my_filter) and CALL_FUNCTION?
# c below has both of these

# tight loop with function call
>>> dis.dis(c)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (values)

3 4 SETUP_LOOP 34 (to 40)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 1 (10)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 22 (to 38)
16 STORE_FAST 1 (i)

4 18 LOAD_GLOBAL 1 (my_filter)
20 LOAD_FAST 1 (i)
22 CALL_FUNCTION 1
24 POP_JUMP_IF_FALSE 14

5 26 LOAD_FAST 0 (values)
28 LOAD_ATTR 2 (append)
30 LOAD_FAST 1 (i)
32 CALL_FUNCTION 1
34 POP_TOP
36 JUMP_ABSOLUTE 14
>> 38 POP_BLOCK

6 >> 40 LOAD_FAST 0 (values)
42 RETURN_VALUE

# tight loop without function call
>>> dis.dis(d)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (values)

3 4 SETUP_LOOP 34 (to 40)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 1 (10)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 22 (to 38)
16 STORE_FAST 1 (i)

4 18 LOAD_FAST 1 (i)
20 LOAD_CONST 2 (5)
22 COMPARE_OP 0 (<)
24 POP_JUMP_IF_FALSE 14

5 26 LOAD_FAST 0 (values)
28 LOAD_ATTR 1 (append)
30 LOAD_FAST 1 (i)
32 CALL_FUNCTION 1
34 POP_TOP
36 JUMP_ABSOLUTE 14
>> 38 POP_BLOCK

6 >> 40 LOAD_FAST 0 (values)
42 RETURN_VALUE

import timeit

>>> timeit.timeit(a) # list comprehension with my_filter
1.2435139456834463
>>> timeit.timeit(b) # list comprehension without my_filter
0.6717423789164627
>>> timeit.timeit(c) # no list comprehension with my_filter
1.326850592144865
>>> timeit.timeit(d) # no list comprehension no my_filter
0.7743895521070954


Why do a and b have the same byte code when disassembled? I would have expected b to have better looking bytecode. Notably I would have thought that a would need a LOAD_GLOBAL ? (my_filter) and a CALL FUNCTION. For example, c is the same as a but without the list comprehension, and it uses these bytecodes these on addresses 18 and 22.



However, even with the same bytecode, b performs much better than a. What's going on here?



Even more interesting, d, which uses a tight loop but does not have the call to my_filter, is faster than b which uses the list comprehension but has the call to my_filter. It looks like the overhead of using a function outweighs the overhead of a tight loop.



My goal here is to try to figure out if I can factor out conditions of a list comprehension into a function to make the list comprehension easier to read.










share|improve this question





















  • 2





    What's your python version? In 3.7, it also disassembles the <listcomp> itself, which is of course quite different for your two functions.

    – georg
    8 hours ago











  • @georg I'm on Python 3.6.5

    – Matthew Moisen
    8 hours ago






  • 1





    The body of a list comprehension is compiled as if it were a nested function. Note the complete lack of any reference to my_filter() in a(), you're obviously not seeing everything in the disassembly.

    – jasonharper
    8 hours ago











  • @georg Got it. Would you like to make an answer? dis.dis(a.__code__.co_consts[1]) and dis.dis(b.__code__.co_consts[1]) shows the difference. If you could show what it looks like in 3.7 that would be great as well.

    – Matthew Moisen
    8 hours ago













6












6








6








What follows is four functions that have the same output, but either written with a list comprehension or a tight loop, and a function call to vs an inline condition.



Interestingly, a and b have the same bytecode when disassembled, however b is much faster than a.



Moreover, d, which uses a tight loop with no function call, is faster than a which uses a list comprehension with a function call.



Why do functions a and b have the same bytecode, and why does b perform much better than a given the same bytecode?



import dis

def my_filter(n):
return n < 5

def a():
# list comprehension with function call
return [i for i in range(10) if my_filter(i)]

def b():
# list comprehension without function call
return [i for i in range(10) if i < 5]

def c():
# tight loop with function call
values = []
for i in range(10):
if my_filter(i):
values.append(i)
return values

def d():
# tight loop without function call
values = []
for i in range(10):
if i < 5:
values.append(i)
return values

assert a() == b() == c() == d()

import sys
>>> sys.version_info[:]
(3, 6, 5, 'final', 0)

# list comprehension with function call
>>> dis.dis(a)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

# list comprehension without function call
>>> dis.dis(b)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBB64270, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

# a and b have the same byte code?
# Why doesn't a have a LOAD_GLOBAL (my_filter) and CALL_FUNCTION?
# c below has both of these

# tight loop with function call
>>> dis.dis(c)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (values)

3 4 SETUP_LOOP 34 (to 40)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 1 (10)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 22 (to 38)
16 STORE_FAST 1 (i)

4 18 LOAD_GLOBAL 1 (my_filter)
20 LOAD_FAST 1 (i)
22 CALL_FUNCTION 1
24 POP_JUMP_IF_FALSE 14

5 26 LOAD_FAST 0 (values)
28 LOAD_ATTR 2 (append)
30 LOAD_FAST 1 (i)
32 CALL_FUNCTION 1
34 POP_TOP
36 JUMP_ABSOLUTE 14
>> 38 POP_BLOCK

6 >> 40 LOAD_FAST 0 (values)
42 RETURN_VALUE

# tight loop without function call
>>> dis.dis(d)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (values)

3 4 SETUP_LOOP 34 (to 40)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 1 (10)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 22 (to 38)
16 STORE_FAST 1 (i)

4 18 LOAD_FAST 1 (i)
20 LOAD_CONST 2 (5)
22 COMPARE_OP 0 (<)
24 POP_JUMP_IF_FALSE 14

5 26 LOAD_FAST 0 (values)
28 LOAD_ATTR 1 (append)
30 LOAD_FAST 1 (i)
32 CALL_FUNCTION 1
34 POP_TOP
36 JUMP_ABSOLUTE 14
>> 38 POP_BLOCK

6 >> 40 LOAD_FAST 0 (values)
42 RETURN_VALUE

import timeit

>>> timeit.timeit(a) # list comprehension with my_filter
1.2435139456834463
>>> timeit.timeit(b) # list comprehension without my_filter
0.6717423789164627
>>> timeit.timeit(c) # no list comprehension with my_filter
1.326850592144865
>>> timeit.timeit(d) # no list comprehension no my_filter
0.7743895521070954


Why do a and b have the same byte code when disassembled? I would have expected b to have better looking bytecode. Notably I would have thought that a would need a LOAD_GLOBAL ? (my_filter) and a CALL FUNCTION. For example, c is the same as a but without the list comprehension, and it uses these bytecodes these on addresses 18 and 22.



However, even with the same bytecode, b performs much better than a. What's going on here?



Even more interesting, d, which uses a tight loop but does not have the call to my_filter, is faster than b which uses the list comprehension but has the call to my_filter. It looks like the overhead of using a function outweighs the overhead of a tight loop.



My goal here is to try to figure out if I can factor out conditions of a list comprehension into a function to make the list comprehension easier to read.










share|improve this question
















What follows is four functions that have the same output, but either written with a list comprehension or a tight loop, and a function call to vs an inline condition.



Interestingly, a and b have the same bytecode when disassembled, however b is much faster than a.



Moreover, d, which uses a tight loop with no function call, is faster than a which uses a list comprehension with a function call.



Why do functions a and b have the same bytecode, and why does b perform much better than a given the same bytecode?



import dis

def my_filter(n):
return n < 5

def a():
# list comprehension with function call
return [i for i in range(10) if my_filter(i)]

def b():
# list comprehension without function call
return [i for i in range(10) if i < 5]

def c():
# tight loop with function call
values = []
for i in range(10):
if my_filter(i):
values.append(i)
return values

def d():
# tight loop without function call
values = []
for i in range(10):
if i < 5:
values.append(i)
return values

assert a() == b() == c() == d()

import sys
>>> sys.version_info[:]
(3, 6, 5, 'final', 0)

# list comprehension with function call
>>> dis.dis(a)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

# list comprehension without function call
>>> dis.dis(b)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBB64270, file "<stdin>", line 2>)
2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

# a and b have the same byte code?
# Why doesn't a have a LOAD_GLOBAL (my_filter) and CALL_FUNCTION?
# c below has both of these

# tight loop with function call
>>> dis.dis(c)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (values)

3 4 SETUP_LOOP 34 (to 40)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 1 (10)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 22 (to 38)
16 STORE_FAST 1 (i)

4 18 LOAD_GLOBAL 1 (my_filter)
20 LOAD_FAST 1 (i)
22 CALL_FUNCTION 1
24 POP_JUMP_IF_FALSE 14

5 26 LOAD_FAST 0 (values)
28 LOAD_ATTR 2 (append)
30 LOAD_FAST 1 (i)
32 CALL_FUNCTION 1
34 POP_TOP
36 JUMP_ABSOLUTE 14
>> 38 POP_BLOCK

6 >> 40 LOAD_FAST 0 (values)
42 RETURN_VALUE

# tight loop without function call
>>> dis.dis(d)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (values)

3 4 SETUP_LOOP 34 (to 40)
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 1 (10)
10 CALL_FUNCTION 1
12 GET_ITER
>> 14 FOR_ITER 22 (to 38)
16 STORE_FAST 1 (i)

4 18 LOAD_FAST 1 (i)
20 LOAD_CONST 2 (5)
22 COMPARE_OP 0 (<)
24 POP_JUMP_IF_FALSE 14

5 26 LOAD_FAST 0 (values)
28 LOAD_ATTR 1 (append)
30 LOAD_FAST 1 (i)
32 CALL_FUNCTION 1
34 POP_TOP
36 JUMP_ABSOLUTE 14
>> 38 POP_BLOCK

6 >> 40 LOAD_FAST 0 (values)
42 RETURN_VALUE

import timeit

>>> timeit.timeit(a) # list comprehension with my_filter
1.2435139456834463
>>> timeit.timeit(b) # list comprehension without my_filter
0.6717423789164627
>>> timeit.timeit(c) # no list comprehension with my_filter
1.326850592144865
>>> timeit.timeit(d) # no list comprehension no my_filter
0.7743895521070954


Why do a and b have the same byte code when disassembled? I would have expected b to have better looking bytecode. Notably I would have thought that a would need a LOAD_GLOBAL ? (my_filter) and a CALL FUNCTION. For example, c is the same as a but without the list comprehension, and it uses these bytecodes these on addresses 18 and 22.



However, even with the same bytecode, b performs much better than a. What's going on here?



Even more interesting, d, which uses a tight loop but does not have the call to my_filter, is faster than b which uses the list comprehension but has the call to my_filter. It looks like the overhead of using a function outweighs the overhead of a tight loop.



My goal here is to try to figure out if I can factor out conditions of a list comprehension into a function to make the list comprehension easier to read.







python python-3.x python-3.6 bytecode






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 8 hours ago







Matthew Moisen

















asked 8 hours ago









Matthew MoisenMatthew Moisen

5,38916 gold badges68 silver badges140 bronze badges




5,38916 gold badges68 silver badges140 bronze badges










  • 2





    What's your python version? In 3.7, it also disassembles the <listcomp> itself, which is of course quite different for your two functions.

    – georg
    8 hours ago











  • @georg I'm on Python 3.6.5

    – Matthew Moisen
    8 hours ago






  • 1





    The body of a list comprehension is compiled as if it were a nested function. Note the complete lack of any reference to my_filter() in a(), you're obviously not seeing everything in the disassembly.

    – jasonharper
    8 hours ago











  • @georg Got it. Would you like to make an answer? dis.dis(a.__code__.co_consts[1]) and dis.dis(b.__code__.co_consts[1]) shows the difference. If you could show what it looks like in 3.7 that would be great as well.

    – Matthew Moisen
    8 hours ago












  • 2





    What's your python version? In 3.7, it also disassembles the <listcomp> itself, which is of course quite different for your two functions.

    – georg
    8 hours ago











  • @georg I'm on Python 3.6.5

    – Matthew Moisen
    8 hours ago






  • 1





    The body of a list comprehension is compiled as if it were a nested function. Note the complete lack of any reference to my_filter() in a(), you're obviously not seeing everything in the disassembly.

    – jasonharper
    8 hours ago











  • @georg Got it. Would you like to make an answer? dis.dis(a.__code__.co_consts[1]) and dis.dis(b.__code__.co_consts[1]) shows the difference. If you could show what it looks like in 3.7 that would be great as well.

    – Matthew Moisen
    8 hours ago







2




2





What's your python version? In 3.7, it also disassembles the <listcomp> itself, which is of course quite different for your two functions.

– georg
8 hours ago





What's your python version? In 3.7, it also disassembles the <listcomp> itself, which is of course quite different for your two functions.

– georg
8 hours ago













@georg I'm on Python 3.6.5

– Matthew Moisen
8 hours ago





@georg I'm on Python 3.6.5

– Matthew Moisen
8 hours ago




1




1





The body of a list comprehension is compiled as if it were a nested function. Note the complete lack of any reference to my_filter() in a(), you're obviously not seeing everything in the disassembly.

– jasonharper
8 hours ago





The body of a list comprehension is compiled as if it were a nested function. Note the complete lack of any reference to my_filter() in a(), you're obviously not seeing everything in the disassembly.

– jasonharper
8 hours ago













@georg Got it. Would you like to make an answer? dis.dis(a.__code__.co_consts[1]) and dis.dis(b.__code__.co_consts[1]) shows the difference. If you could show what it looks like in 3.7 that would be great as well.

– Matthew Moisen
8 hours ago





@georg Got it. Would you like to make an answer? dis.dis(a.__code__.co_consts[1]) and dis.dis(b.__code__.co_consts[1]) shows the difference. If you could show what it looks like in 3.7 that would be great as well.

– Matthew Moisen
8 hours ago












2 Answers
2






active

oldest

votes


















5















Note that both bytecodes for a and b only run <listcomp> objects defined elsewhere.



2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)


Since the wrapper functions a and b are identical, their bytecodes are the same, only the addresses of listcomps are different.



In python 3.7 the dis module also prints the listcomps, here's the complete code and the output:



import sys
import dis

def my_filter(n):
return n < 5

def a():
# list comprehension with function call
return [i for i in range(10) if my_filter(i)]

def b():
# list comprehension without function call
return [i for i in range(10) if i < 5]

print(sys.version)
print('-' * 70)
dis.dis(a)
print('-' * 70)
dis.dis(b)


--



3.7.3 (default, May 19 2019, 21:16:26) 
[Clang 10.0.1 (clang-1001.0.46.4)]
----------------------------------------------------------------------
9 0 LOAD_CONST 1 (<code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>)
2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

Disassembly of <code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>:
9 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 16 (to 22)
6 STORE_FAST 1 (i)
8 LOAD_GLOBAL 0 (my_filter)
10 LOAD_FAST 1 (i)
12 CALL_FUNCTION 1
14 POP_JUMP_IF_FALSE 4
16 LOAD_FAST 1 (i)
18 LIST_APPEND 2
20 JUMP_ABSOLUTE 4
>> 22 RETURN_VALUE
----------------------------------------------------------------------
13 0 LOAD_CONST 1 (<code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>)
2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_GLOBAL 0 (range)
8 LOAD_CONST 3 (10)
10 CALL_FUNCTION 1
12 GET_ITER
14 CALL_FUNCTION 1
16 RETURN_VALUE

Disassembly of <code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>:
13 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 16 (to 22)
6 STORE_FAST 1 (i)
8 LOAD_FAST 1 (i)
10 LOAD_CONST 0 (5)
12 COMPARE_OP 0 (<)
14 POP_JUMP_IF_FALSE 4
16 LOAD_FAST 1 (i)
18 LIST_APPEND 2
20 JUMP_ABSOLUTE 4
>> 22 RETURN_VALUE


For pythons < 3.7. see Python: analyze a list comprehension with dis






share|improve this answer

























  • I have a follow-up Hail Mary here - would you mind taking a look?

    – Matthew Moisen
    7 hours ago


















1















List-Comprehensions are converted to inner functions, because they built a separate namespace. The inner functions for the LC in a and b differ:



>>> dis.dis(a.__code__.co_consts[1])
3 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 16 (to 22)
6 STORE_FAST 1 (i)
8 LOAD_GLOBAL 0 (my_filter)
10 LOAD_FAST 1 (i)
12 CALL_FUNCTION 1
14 POP_JUMP_IF_FALSE 4
16 LOAD_FAST 1 (i)
18 LIST_APPEND 2
20 JUMP_ABSOLUTE 4
>> 22 RETURN_VALUE
>>> dis.dis(b.__code__.co_consts[1])
3 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 16 (to 22)
6 STORE_FAST 1 (i)
8 LOAD_FAST 1 (i)
10 LOAD_CONST 0 (5)
12 COMPARE_OP 0 (<)
14 POP_JUMP_IF_FALSE 4
16 LOAD_FAST 1 (i)
18 LIST_APPEND 2
20 JUMP_ABSOLUTE 4
>> 22 RETURN_VALUE


There you see the function call in a and the comparision in b.






share|improve this answer



























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f57647670%2fwhy-do-these-two-functions-have-the-same-bytecode-when-disassembled-under-dis-di%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    5















    Note that both bytecodes for a and b only run <listcomp> objects defined elsewhere.



    2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)


    Since the wrapper functions a and b are identical, their bytecodes are the same, only the addresses of listcomps are different.



    In python 3.7 the dis module also prints the listcomps, here's the complete code and the output:



    import sys
    import dis

    def my_filter(n):
    return n < 5

    def a():
    # list comprehension with function call
    return [i for i in range(10) if my_filter(i)]

    def b():
    # list comprehension without function call
    return [i for i in range(10) if i < 5]

    print(sys.version)
    print('-' * 70)
    dis.dis(a)
    print('-' * 70)
    dis.dis(b)


    --



    3.7.3 (default, May 19 2019, 21:16:26) 
    [Clang 10.0.1 (clang-1001.0.46.4)]
    ----------------------------------------------------------------------
    9 0 LOAD_CONST 1 (<code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>)
    2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
    4 MAKE_FUNCTION 0
    6 LOAD_GLOBAL 0 (range)
    8 LOAD_CONST 3 (10)
    10 CALL_FUNCTION 1
    12 GET_ITER
    14 CALL_FUNCTION 1
    16 RETURN_VALUE

    Disassembly of <code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>:
    9 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_GLOBAL 0 (my_filter)
    10 LOAD_FAST 1 (i)
    12 CALL_FUNCTION 1
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE
    ----------------------------------------------------------------------
    13 0 LOAD_CONST 1 (<code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>)
    2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
    4 MAKE_FUNCTION 0
    6 LOAD_GLOBAL 0 (range)
    8 LOAD_CONST 3 (10)
    10 CALL_FUNCTION 1
    12 GET_ITER
    14 CALL_FUNCTION 1
    16 RETURN_VALUE

    Disassembly of <code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>:
    13 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_FAST 1 (i)
    10 LOAD_CONST 0 (5)
    12 COMPARE_OP 0 (<)
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE


    For pythons < 3.7. see Python: analyze a list comprehension with dis






    share|improve this answer

























    • I have a follow-up Hail Mary here - would you mind taking a look?

      – Matthew Moisen
      7 hours ago















    5















    Note that both bytecodes for a and b only run <listcomp> objects defined elsewhere.



    2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)


    Since the wrapper functions a and b are identical, their bytecodes are the same, only the addresses of listcomps are different.



    In python 3.7 the dis module also prints the listcomps, here's the complete code and the output:



    import sys
    import dis

    def my_filter(n):
    return n < 5

    def a():
    # list comprehension with function call
    return [i for i in range(10) if my_filter(i)]

    def b():
    # list comprehension without function call
    return [i for i in range(10) if i < 5]

    print(sys.version)
    print('-' * 70)
    dis.dis(a)
    print('-' * 70)
    dis.dis(b)


    --



    3.7.3 (default, May 19 2019, 21:16:26) 
    [Clang 10.0.1 (clang-1001.0.46.4)]
    ----------------------------------------------------------------------
    9 0 LOAD_CONST 1 (<code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>)
    2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
    4 MAKE_FUNCTION 0
    6 LOAD_GLOBAL 0 (range)
    8 LOAD_CONST 3 (10)
    10 CALL_FUNCTION 1
    12 GET_ITER
    14 CALL_FUNCTION 1
    16 RETURN_VALUE

    Disassembly of <code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>:
    9 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_GLOBAL 0 (my_filter)
    10 LOAD_FAST 1 (i)
    12 CALL_FUNCTION 1
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE
    ----------------------------------------------------------------------
    13 0 LOAD_CONST 1 (<code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>)
    2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
    4 MAKE_FUNCTION 0
    6 LOAD_GLOBAL 0 (range)
    8 LOAD_CONST 3 (10)
    10 CALL_FUNCTION 1
    12 GET_ITER
    14 CALL_FUNCTION 1
    16 RETURN_VALUE

    Disassembly of <code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>:
    13 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_FAST 1 (i)
    10 LOAD_CONST 0 (5)
    12 COMPARE_OP 0 (<)
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE


    For pythons < 3.7. see Python: analyze a list comprehension with dis






    share|improve this answer

























    • I have a follow-up Hail Mary here - would you mind taking a look?

      – Matthew Moisen
      7 hours ago













    5














    5










    5









    Note that both bytecodes for a and b only run <listcomp> objects defined elsewhere.



    2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)


    Since the wrapper functions a and b are identical, their bytecodes are the same, only the addresses of listcomps are different.



    In python 3.7 the dis module also prints the listcomps, here's the complete code and the output:



    import sys
    import dis

    def my_filter(n):
    return n < 5

    def a():
    # list comprehension with function call
    return [i for i in range(10) if my_filter(i)]

    def b():
    # list comprehension without function call
    return [i for i in range(10) if i < 5]

    print(sys.version)
    print('-' * 70)
    dis.dis(a)
    print('-' * 70)
    dis.dis(b)


    --



    3.7.3 (default, May 19 2019, 21:16:26) 
    [Clang 10.0.1 (clang-1001.0.46.4)]
    ----------------------------------------------------------------------
    9 0 LOAD_CONST 1 (<code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>)
    2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
    4 MAKE_FUNCTION 0
    6 LOAD_GLOBAL 0 (range)
    8 LOAD_CONST 3 (10)
    10 CALL_FUNCTION 1
    12 GET_ITER
    14 CALL_FUNCTION 1
    16 RETURN_VALUE

    Disassembly of <code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>:
    9 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_GLOBAL 0 (my_filter)
    10 LOAD_FAST 1 (i)
    12 CALL_FUNCTION 1
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE
    ----------------------------------------------------------------------
    13 0 LOAD_CONST 1 (<code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>)
    2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
    4 MAKE_FUNCTION 0
    6 LOAD_GLOBAL 0 (range)
    8 LOAD_CONST 3 (10)
    10 CALL_FUNCTION 1
    12 GET_ITER
    14 CALL_FUNCTION 1
    16 RETURN_VALUE

    Disassembly of <code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>:
    13 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_FAST 1 (i)
    10 LOAD_CONST 0 (5)
    12 COMPARE_OP 0 (<)
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE


    For pythons < 3.7. see Python: analyze a list comprehension with dis






    share|improve this answer













    Note that both bytecodes for a and b only run <listcomp> objects defined elsewhere.



    2 0 LOAD_CONST 1 (<code object <listcomp> at 0x00000211CBE8B300, file "<stdin>", line 2>)


    Since the wrapper functions a and b are identical, their bytecodes are the same, only the addresses of listcomps are different.



    In python 3.7 the dis module also prints the listcomps, here's the complete code and the output:



    import sys
    import dis

    def my_filter(n):
    return n < 5

    def a():
    # list comprehension with function call
    return [i for i in range(10) if my_filter(i)]

    def b():
    # list comprehension without function call
    return [i for i in range(10) if i < 5]

    print(sys.version)
    print('-' * 70)
    dis.dis(a)
    print('-' * 70)
    dis.dis(b)


    --



    3.7.3 (default, May 19 2019, 21:16:26) 
    [Clang 10.0.1 (clang-1001.0.46.4)]
    ----------------------------------------------------------------------
    9 0 LOAD_CONST 1 (<code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>)
    2 LOAD_CONST 2 ('a.<locals>.<listcomp>')
    4 MAKE_FUNCTION 0
    6 LOAD_GLOBAL 0 (range)
    8 LOAD_CONST 3 (10)
    10 CALL_FUNCTION 1
    12 GET_ITER
    14 CALL_FUNCTION 1
    16 RETURN_VALUE

    Disassembly of <code object <listcomp> at 0x1065c61e0, file "/w/test/x.py", line 9>:
    9 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_GLOBAL 0 (my_filter)
    10 LOAD_FAST 1 (i)
    12 CALL_FUNCTION 1
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE
    ----------------------------------------------------------------------
    13 0 LOAD_CONST 1 (<code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>)
    2 LOAD_CONST 2 ('b.<locals>.<listcomp>')
    4 MAKE_FUNCTION 0
    6 LOAD_GLOBAL 0 (range)
    8 LOAD_CONST 3 (10)
    10 CALL_FUNCTION 1
    12 GET_ITER
    14 CALL_FUNCTION 1
    16 RETURN_VALUE

    Disassembly of <code object <listcomp> at 0x1066188a0, file "/w/test/x.py", line 13>:
    13 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_FAST 1 (i)
    10 LOAD_CONST 0 (5)
    12 COMPARE_OP 0 (<)
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE


    For pythons < 3.7. see Python: analyze a list comprehension with dis







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 7 hours ago









    georggeorg

    164k36 gold badges220 silver badges320 bronze badges




    164k36 gold badges220 silver badges320 bronze badges















    • I have a follow-up Hail Mary here - would you mind taking a look?

      – Matthew Moisen
      7 hours ago

















    • I have a follow-up Hail Mary here - would you mind taking a look?

      – Matthew Moisen
      7 hours ago
















    I have a follow-up Hail Mary here - would you mind taking a look?

    – Matthew Moisen
    7 hours ago





    I have a follow-up Hail Mary here - would you mind taking a look?

    – Matthew Moisen
    7 hours ago













    1















    List-Comprehensions are converted to inner functions, because they built a separate namespace. The inner functions for the LC in a and b differ:



    >>> dis.dis(a.__code__.co_consts[1])
    3 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_GLOBAL 0 (my_filter)
    10 LOAD_FAST 1 (i)
    12 CALL_FUNCTION 1
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE
    >>> dis.dis(b.__code__.co_consts[1])
    3 0 BUILD_LIST 0
    2 LOAD_FAST 0 (.0)
    >> 4 FOR_ITER 16 (to 22)
    6 STORE_FAST 1 (i)
    8 LOAD_FAST 1 (i)
    10 LOAD_CONST 0 (5)
    12 COMPARE_OP 0 (<)
    14 POP_JUMP_IF_FALSE 4
    16 LOAD_FAST 1 (i)
    18 LIST_APPEND 2
    20 JUMP_ABSOLUTE 4
    >> 22 RETURN_VALUE


    There you see the function call in a and the comparision in b.






    share|improve this answer





























      1















      List-Comprehensions are converted to inner functions, because they built a separate namespace. The inner functions for the LC in a and b differ:



      >>> dis.dis(a.__code__.co_consts[1])
      3 0 BUILD_LIST 0
      2 LOAD_FAST 0 (.0)
      >> 4 FOR_ITER 16 (to 22)
      6 STORE_FAST 1 (i)
      8 LOAD_GLOBAL 0 (my_filter)
      10 LOAD_FAST 1 (i)
      12 CALL_FUNCTION 1
      14 POP_JUMP_IF_FALSE 4
      16 LOAD_FAST 1 (i)
      18 LIST_APPEND 2
      20 JUMP_ABSOLUTE 4
      >> 22 RETURN_VALUE
      >>> dis.dis(b.__code__.co_consts[1])
      3 0 BUILD_LIST 0
      2 LOAD_FAST 0 (.0)
      >> 4 FOR_ITER 16 (to 22)
      6 STORE_FAST 1 (i)
      8 LOAD_FAST 1 (i)
      10 LOAD_CONST 0 (5)
      12 COMPARE_OP 0 (<)
      14 POP_JUMP_IF_FALSE 4
      16 LOAD_FAST 1 (i)
      18 LIST_APPEND 2
      20 JUMP_ABSOLUTE 4
      >> 22 RETURN_VALUE


      There you see the function call in a and the comparision in b.






      share|improve this answer



























        1














        1










        1









        List-Comprehensions are converted to inner functions, because they built a separate namespace. The inner functions for the LC in a and b differ:



        >>> dis.dis(a.__code__.co_consts[1])
        3 0 BUILD_LIST 0
        2 LOAD_FAST 0 (.0)
        >> 4 FOR_ITER 16 (to 22)
        6 STORE_FAST 1 (i)
        8 LOAD_GLOBAL 0 (my_filter)
        10 LOAD_FAST 1 (i)
        12 CALL_FUNCTION 1
        14 POP_JUMP_IF_FALSE 4
        16 LOAD_FAST 1 (i)
        18 LIST_APPEND 2
        20 JUMP_ABSOLUTE 4
        >> 22 RETURN_VALUE
        >>> dis.dis(b.__code__.co_consts[1])
        3 0 BUILD_LIST 0
        2 LOAD_FAST 0 (.0)
        >> 4 FOR_ITER 16 (to 22)
        6 STORE_FAST 1 (i)
        8 LOAD_FAST 1 (i)
        10 LOAD_CONST 0 (5)
        12 COMPARE_OP 0 (<)
        14 POP_JUMP_IF_FALSE 4
        16 LOAD_FAST 1 (i)
        18 LIST_APPEND 2
        20 JUMP_ABSOLUTE 4
        >> 22 RETURN_VALUE


        There you see the function call in a and the comparision in b.






        share|improve this answer













        List-Comprehensions are converted to inner functions, because they built a separate namespace. The inner functions for the LC in a and b differ:



        >>> dis.dis(a.__code__.co_consts[1])
        3 0 BUILD_LIST 0
        2 LOAD_FAST 0 (.0)
        >> 4 FOR_ITER 16 (to 22)
        6 STORE_FAST 1 (i)
        8 LOAD_GLOBAL 0 (my_filter)
        10 LOAD_FAST 1 (i)
        12 CALL_FUNCTION 1
        14 POP_JUMP_IF_FALSE 4
        16 LOAD_FAST 1 (i)
        18 LIST_APPEND 2
        20 JUMP_ABSOLUTE 4
        >> 22 RETURN_VALUE
        >>> dis.dis(b.__code__.co_consts[1])
        3 0 BUILD_LIST 0
        2 LOAD_FAST 0 (.0)
        >> 4 FOR_ITER 16 (to 22)
        6 STORE_FAST 1 (i)
        8 LOAD_FAST 1 (i)
        10 LOAD_CONST 0 (5)
        12 COMPARE_OP 0 (<)
        14 POP_JUMP_IF_FALSE 4
        16 LOAD_FAST 1 (i)
        18 LIST_APPEND 2
        20 JUMP_ABSOLUTE 4
        >> 22 RETURN_VALUE


        There you see the function call in a and the comparision in b.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 8 hours ago









        DanielDaniel

        33.8k4 gold badges32 silver badges63 bronze badges




        33.8k4 gold badges32 silver badges63 bronze badges






























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f57647670%2fwhy-do-these-two-functions-have-the-same-bytecode-when-disassembled-under-dis-di%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

            Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

            Ласкавець круглолистий Зміст Опис | Поширення | Галерея | Примітки | Посилання | Навігаційне меню58171138361-22960890446Bupleurum rotundifoliumEuro+Med PlantbasePlants of the World Online — Kew ScienceGermplasm Resources Information Network (GRIN)Ласкавецькн. VI : Літери Ком — Левиправивши або дописавши її