【问题标题】:using closures to remember previous function calls [closed]使用闭包来记住以前的函数调用[关闭]
【发布时间】:2020-12-18 16:22:09
【问题描述】:

我开始了我的一个新项目,我想创建一个函数,我们将其命名为foo,它会记住之前对其进行的调用。

因此,例如,如果函数应该返回最后使用的参数,我们应该有这个:

print(foo(2), foo(7), foo('a'))

打印出来:

None 2 7

问题

我们如何创建一个装饰器函数,例如称为bar,它打印给定的参数,除非前一个函数调用与前一个函数调用相同,在这种情况下,该函数不打印任何内容并简单地返回 None。

我做了什么?

到目前为止,我已经能够创建函数的骨架,如下所示:

@bar
def printer(*args):
    print(*args)

在 bar 函数中,我应该以某种方式检查上一个调用,但我不知道如何!我不想使用全局变量或其他东西,而只想使用该函数。我假设我需要为 barfoo 函数使用闭包。你能告诉我如何实现它们吗?

注意 这就是这些调用应该发生的情况:

printer("a")  # prints a
printer("a")  # only returns None 
printer("a")  # only returns None
printer("b")  # prints b
printer("a")  # prints a

【问题讨论】:

  • 在您的情况下应该进行打印的函数应该驻留在 bar 装饰器函数中,并且它将是一个具有自己的内部函数的函数,该函数将使用参数调用输入函数已通过,然后您可以在bar 形成的闭包中管理这些参数。请查看 decorator basics 了解装饰器的工作原理。

标签: python closures decorator wrapper python-decorators


【解决方案1】:

首先编写一个您希望装饰器生成的foo 版本,例如

def foo(arg, prev=[]):
    if arg in prev[-1:]:
        return None
    else:
        prev.append(arg)
        return arg

>>> print(foo(1), foo(2), foo(2), foo(3))
1 2 None 3

现在你知道你想让装饰器做什么了。

def bar(f):
    def bar(arg, prev=[]):
        if arg in prev[-1:]:
            return None
        else:
            prev.append(arg)
            return(f(arg))
    return bar

现在重新定义foo,不带内存,但包裹在装饰器中:

@bar
def foo(arg):
    return arg

>>> print(foo(1), foo(2), foo(2), foo(3))
1 2 None 3

【讨论】:

  • 似乎工作得很好,谢谢 :) 你能解释一下为什么prev 在每次调用后都会保持其值并且不会被重置吗?
  • 这是一个可变的默认参数,它被广泛认为是邪恶的(谷歌它)。 Python 在定义函数时设置默认参数值,并且它们在调用中保持不变。如果它是一个像列表这样的可变对象,它就是 reference 在对函数的调用中持续存在,因此它的工作方式很像其他语言所称的静态变量(但不是 看起来 像一个)。一个用例是记住昂贵的函数调用的结果,以便一个函数在使用相同的参数第二次调用时可以返回一个预先准备好的结果,而不是重新进行工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-10
  • 1970-01-01
相关资源
最近更新 更多