15

我不是指闭包,其中外部函数返回内部函数,或者特别是记忆化。在某些情况下,我想编写一个递归函数,可能带有记忆,并且在外部函数中初始化字典或其他一些数据结构似乎要简单得多,然后有一个递归辅助函数写入和访问外部函数的字典和参数。这就是我的意思——

def foo(arr, l):
   cache = {}
   result = []

   def recursive_foo_helper(i, j, k):
      # some code that depends on arr, l, i, j, k, cache, and result

   for (x, y) in arr:
      if recursive_foo_helper(x, y, k):
         return result
   return None

而不是使用一些超长签名单独声明辅助函数,例如,

recursive_foo_helper(arr, l, i, j, k, cache={}, result=[])

我已经读过这样做是非常标准的记忆,但我很好奇是否就只为递归辅助函数做是否可以达成共识。

4

4 回答 4

9

There are a lot of good reasons. Personally, I often use nested functions to keep the namespace clean. It's especially useful within object methods :

class Foo(object):
    def bar(self):
        def baz(val):
            return val
        return [ baz(i) for i in range(1,101) ]

If I declare baz outside of bar, I either need to make it a method of Foo, or expose it to the entire package.

于 2013-06-10T22:47:23.097 回答
7

我使用嵌套函数从列表中查找匹配项:

def get_exact(data, key, match):
    def is_match(item):
        if (key in item) and (item[key].lower() == match.lower()):
            return item
        return False
    return [i for i in data if is_match(i)]

项目中没有其他调用需要使用is_match(item),为什么要单独声明呢?

但是,我会说,在我的示例中,在 10,000 次迭代中,在is_match()外部声明get_exact()确实会快约 0.04 秒。

def is_match(item, key, match):
    if (key in item) and (item[key].lower() == match.lower()):
        return item
    return False

def get_exact(data, key, match):
    return [i for i in data if is_match(i, key, match)]
于 2013-06-10T22:32:49.773 回答
4

我通常使用闭包,但是您建议的另一种方式(我有时称为 Wrapper)也非常有用,并且根据我的个人经验,它可以正常工作。我从来没有人告诉我要避免这种风格。如果您的代码有效并且可读(我认为是这样),那就去吧!

于 2013-06-10T23:12:09.483 回答
1

我想说按照您的建议使用闭包更清洁,但nonlocal如果您想重新绑定引用,确实需要 Python3 中的关键字。对于可变对象,显然可以修改它们。

同时,在 Python2 中看到 defaultarg hacks/idioms 是很常见的

嵌套函数的一个(也许是唯一的)缺点是难以进行单元测试。

为了确保缓存不会无限增长,您还需要一种删除项目的方法(例如最近最少使用的)

于 2013-06-10T22:36:38.903 回答