我一直在学习 Python 函数和一般函数,我遇到了匿名函数的想法,它的优点,除其他外,显然是能够保持命名空间干净以及不分配额外的内存,因为一个函数仅在分配给变量后才执行。
在 Python 中,据我所知,创建匿名函数的唯一方法是将它们包装在另一个函数中。所以我想到了为代码中的多个匿名函数创建一个容器并通过选择器寻址它们的想法,这实际上是使用参数调用包装器:
def anonwrap(selector):
if selector == "addition":
def anon(param1, param2):
return param1 + param2
return anon
elif selector == "the meaning of life":
def anon(param1):
return param1 + " 42"
return anon
else:
def anon(*args, **kwargs):
print("no idea")
return anon
select = anonwrap("addition")
print(select(10, 20))
select = anonwrap("the meaning of life")
print(select("the meaning of life is"))
select = anonwrap("hello")
print(select("blah", 9001))
我的问题是,一旦在代码中定义了 anonwrap
函数,解释器是自动为所有内部函数分配内存,还是只为特定的内部函数分配内存?从主代码调用?
这段代码到底有多有效?
最佳答案
据我所知,Python 会自动为所有内部函数创建代码对象并将它们保存为常量:
>>> anonwrap.__code__.co_consts
(None,
'addition',
<code object anon at 0x0000022BB354DD20, file "<ipython-input-78-ab41b0534822>", line 3>,
'anonwrap.<locals>.anon',
'the meaning of life',
<code object anon at 0x0000022BB354D780, file "<ipython-input-78-ab41b0534822>", line 7>,
<code object anon at 0x0000022BB354DE40, file "<ipython-input-78-ab41b0534822>", line 11>)
但它只会在调用 anonwrap
时“命中”适当的分支时创建一个函数(MAKE_FUNCTION
操作码):
import dis
dis.dis(anonwrap)
2 0 LOAD_FAST 0 (selector)
2 LOAD_CONST 1 ('addition')
4 COMPARE_OP 2 (==)
6 POP_JUMP_IF_FALSE 20
3 8 LOAD_CONST 2 (<code object anon at 0x0000022BB3434A50, file "<ipython-input-74-bb454d2da558>", line 3>)
10 LOAD_CONST 3 ('anonwrap.<locals>.anon')
12 MAKE_FUNCTION 0
14 STORE_FAST 1 (anon)
5 16 LOAD_FAST 1 (anon)
18 RETURN_VALUE
6 >> 20 LOAD_FAST 0 (selector)
22 LOAD_CONST 4 ('the meaning of life')
24 COMPARE_OP 2 (==)
26 POP_JUMP_IF_FALSE 40
7 28 LOAD_CONST 5 (<code object anon at 0x0000022BB354DC00, file "<ipython-input-74-bb454d2da558>", line 7>)
30 LOAD_CONST 3 ('anonwrap.<locals>.anon')
32 MAKE_FUNCTION 0
34 STORE_FAST 1 (anon)
9 36 LOAD_FAST 1 (anon)
38 RETURN_VALUE
11 >> 40 LOAD_CONST 6 (<code object anon at 0x0000022BB354DC90, file "<ipython-input-74-bb454d2da558>", line 11>)
42 LOAD_CONST 3 ('anonwrap.<locals>.anon')
44 MAKE_FUNCTION 0
46 STORE_FAST 1 (anon)
13 48 LOAD_FAST 1 (anon)
50 RETURN_VALUE
52 LOAD_CONST 0 (None)
54 RETURN_VALUE
我个人会说代码本身不是很有效,既不利于将来的维护,也不利于性能。创建代码对象只完成一次,但将这些代码对象转换(或编译 - 不确定此处的语言)为函数对象可能有点昂贵。
一个额外的评论:如果你想保持命名空间干净,你通常使用子模块(甚至类)来“捆绑”功能。内部函数(或者你称之为“匿名函数”)主要用于 closures (例如 decorators )。
关于python - 多个匿名 Python 函数的包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45569328/