为什么2个不同的python lambda具有相同的字节码?

时间:2017-06-15 18:42:37

标签: python lambda cpython

我看到一些我不理解的行为。我认为python函数的字节码是为了产生结果而被执行的,但是在这里我有2个不同的lambda函数,它们具有相同的字节码,但显然做了不同的事情。怎么会这样?

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))

生成此输出:

a =  b'|\x00\x00d\x01\x00\x17S'
b =  b'|\x00\x00d\x01\x00\x17S'
5 4

2 个答案:

答案 0 :(得分:5)

字节码不是代码对象中唯一的东西。如果您使用dis.dis对这些函数进行反汇编,您可以看到发生了什么:

>>> 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

正在发生的事情是,还有一个与代码对象相关的常量元组。字节代码只是表示将常量加载到该元组的索引处。它们都具有相同的字节代码,但从元组加载不同的值。您可以使用co_consts属性查看它:

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

您也可以更改此功能以使用其他功能:

>>> 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

答案 1 :(得分:4)

因为竞争对手不同:

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