多个匿名 Python 函数的包装器



我一直在学习 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

就我个人而言,我会说代码本身不是很有效,无论是对未来的维护还是对性能。创建代码对象只完成一次,但将这些转换为函数对象(或编译 - 不确定这里的语言(可能有点昂贵。


另外一个注释:如果你想保持命名空间的清洁,你通常使用子模块(甚至类(来"捆绑"函数。内部函数(或您称之为"匿名函数"(主要用于闭包(例如装饰器(。

最新更新