包含多个匿名Python函数的包装器

时间:2017-08-08 13:12:01

标签: python function wrapper anonymous

我一直在学习Python函数和函数,我遇到了匿名函数的概念,其中的优点显然是保持名称空间清洁以及不分配额外内存的能力,因为函数只有在分配给变量后才会执行。

在Python中,根据我的理解,创建匿名函数的唯一方法是将它们包装在另一个函数中。所以我提出了在代码中为多个匿名函数创建单个容器并通过选择器解决它们的想法,该选择器本质上是用参数调用包装器:

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let completeAction = UITableViewRowAction(style: .normal, title: "Complete", handler: { (action, indexPath) in
        if action.title == "Complete"{
            action.title = "Incomplete"
            cell?.accessoryType = UITableViewCellAccessoryType.checkmark
        }
        else{
            cell?.accessoryType = UITableViewCellAccessoryType.none
            action.title = "Complete"
        }
        tableView.setEditing(false, animated: true)
    })
    completeAction.backgroundColor = .blue
    return [completeAction]
}

我的问题是,一旦在代码中定义了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)) 函数,解释器是否会为所有内部函数自动分配内存,或者只有在从特定内部函数调用后才为特定内部函数分配内存。主要代码?

这段代码的效果如何?

1 个答案:

答案 0 :(得分:2)

据我所知,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)。