Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why 2 different python lambda's have the same bytecode?

I'm seeing some behavior that I don't understand. I thought the bytecode of a python function is what gets executed to produce a result, but here I have 2 different lambda functions, that have the same exact bytecode, but obviously do different things. How can this be?

a = lambda x: x+4
b = lambda y: y+3
print('a = ', a.__code__.co_code)
print('b = ', b.__code__.co_code)
print(a(1), b(1))

Produces this output:

a =  b'|\x00\x00d\x01\x00\x17S'
b =  b'|\x00\x00d\x01\x00\x17S'
5 4
like image 922
dcmm88 Avatar asked Apr 05 '26 16:04

dcmm88


1 Answers

Byte-code is not the only thing in the code object. If you dissassemble the functions using dis.dis you can see what is happening:

>>> import dis
>>> a = lambda x: x + 4
>>> b = lambda y: y + 3
>>> dis.dis(a)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (4)
              6 BINARY_ADD
              7 RETURN_VALUE
>>> dis.dis(b)
  1           0 LOAD_FAST                0 (y)
              3 LOAD_CONST               1 (3)
              6 BINARY_ADD
              7 RETURN_VALUE

What is happening is that there is also a tuple of constants assosciated with the code objects. The byte code just says to load the constant at an index from that tuple. They both have the same byte code, but load different values from the tuple. You can see it with the co_consts attribute:

>>> a.__code__.co_consts
(None, 4)
>>> b.__code__.co_consts
(None, 3)

You can change this too to make a different function:

>>> import types
>>> c_code = types.CodeType(
    a.__code__.co_argcount, a.__code__.co_kwonlyargcount, a.__code__.co_nlocals,
    a.__code__.co_stacksize, a.__code__.co_flags, a.__code__.co_code, (None, 5),
    a.__code__.co_names, a.__code__.co_varnames, a.__code__.co_filename,
    a.__code__.co_name, a.__code__.co_firstlineno, a.__code__.co_lnotab,
    a.__code__.co_freevars, a.__code__.co_cellvars
)
>>> c = types.FunctionType(c_code, globals())
>>> a(0)
4
>>> c(0)
5
like image 77
Artyer Avatar answered Apr 08 '26 04:04

Artyer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!