提问人:david 提问时间:3/30/2023 更新时间:3/30/2023 访问量:60
返回函数或 lambda 函数有区别吗?
Is there a difference in returning a function or a lambda function?
问:
以下两个代码之间是否有区别(甚至是微妙的)? (第二代码有什么特殊用例吗?
- 代码 1
def f(n):
def g(x):
return x * n
return g
- 代码 2
def f(n):
def g(x):
return x * n
return lambda y: g(y)
答:
1赞
Mous
3/30/2023
#1
如果我们使用 Python 内置的 CodeObject 反汇编器模块,函数中的许多差异是显而易见的。这在 3.11 中会有所不同,但我还没有从 3.10 更新。dis
对于第一个函数
2 0 LOAD_CLOSURE 0 (n)
2 BUILD_TUPLE 1
4 LOAD_CONST 1 (<code object g at 0x000001F59E179000, file "<pyshell#2>", line 2>)
6 LOAD_CONST 2 ('f.<locals>.g')
8 MAKE_FUNCTION 8 (closure)
10 STORE_FAST 1 (g)
4 12 LOAD_FAST 1 (g)
14 RETURN_VALUE
Disassembly of <code object g at 0x000001F59E179000, file "<pyshell#2>", line 2>:
3 0 LOAD_FAST 0 (x)
2 LOAD_DEREF 0 (n)
4 BINARY_MULTIPLY
6 RETURN_VALUE
对于第二个:
2 0 LOAD_CLOSURE 1 (n)
2 BUILD_TUPLE 1
4 LOAD_CONST 1 (<code object g at 0x000001F59E1A52C0, file "<pyshell#5>", line 2>)
6 LOAD_CONST 2 ('f.<locals>.g')
8 MAKE_FUNCTION 8 (closure)
10 STORE_DEREF 0 (g)
4 12 LOAD_CLOSURE 0 (g)
14 BUILD_TUPLE 1
16 LOAD_CONST 3 (<code object <lambda> at 0x000001F59E1A5420, file "<pyshell#5>", line 4>)
18 LOAD_CONST 4 ('f.<locals>.<lambda>')
20 MAKE_FUNCTION 8 (closure)
22 RETURN_VALUE
Disassembly of <code object g at 0x000001F59E1A52C0, file "<pyshell#5>", line 2>:
3 0 LOAD_FAST 0 (x)
2 LOAD_DEREF 0 (n)
4 BINARY_MULTIPLY
6 RETURN_VALUE
Disassembly of <code object <lambda> at 0x000001F59E1A5420, file "<pyshell#5>", line 4>:
4 0 LOAD_DEREF 0 (g)
2 LOAD_FAST 0 (y)
4 CALL_FUNCTION 1
6 RETURN_VALUE
每个函数上不同的属性属性是__code__
co_cellvars
-'n'
也存在于第二个函数中co_code
- 第二个函数在返回之前构建一个 lambda;第一个函数直接返回g
co_consts
- 第二个函数包含两个 CodeObject(以及两个相应的名称),而第一个函数仅包含一个 CodeObject 及其名称co_lines
- 该方法在迭代时将返回不同的值,这是不同的直接结果co_lines
co_code
co_lnotab
- (在 3.11 中已弃用)属性是该方法的更节省空间的版本co_lnotab
co_lines
co_nlocals
- 我不确定为什么会有所不同co_varnames
-g
存在于第一个函数中,因为它在第一个函数中直接引用。但是,在第二个函数中,它仅在 lambda 作用域内被引用,因此出现在 lambda 的自由变量中。f.__code__.co_consts[3].co_freevars
最后,正如 Michael 在注释中指出的那样,所有 lambda 函数(例如此处返回的函数)都是 .__name__
'<lambda>'
评论
g
__name__
__code__
__name__
g
g
g
def f(n): return lambda x: x * n
__name__
__code__