python - 多个匿名 Python 函数的包装器

标签 python function wrapper anonymous

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

相关文章:

r - 防止 R 中的函数覆盖

c++ - 为什么 std::reference_wrapper 不是默认可构造的?

c++ - 模板区域中的不可推导上下文

bash - 如何输出 Bash 函数的每个参数?

python - simplejson - 编码 regexp\d+

python - 值错误 : invalid literal for int( ) with base 10: '262,400,000'

python - 为什么定义在 NumPy 文档字符串部分的冒号前有一个空格?

javascript - eval 与函数构造函数

java - 在 Eclipse 中快速实现包装(委托(delegate)方法)?

python - 如何将行标题添加到以下 matplotlib 代码中?