从函数返回函数时出现作用域错误

Scope error when returning function from function

提问人:teepee 提问时间:1/22/2022 更新时间:1/22/2022 访问量:137

问:

我在 python 中使用函数生成器时遇到了问题,即从函数返回函数,其中一些输入是通过外部函数的参数定义的,从而产生一个具有较低 arity 的函数。我以前在其他情况下使用过这种方法,没有问题,但在这种情况下我遇到了错误,无法理解原因。我有以下函数来生成一个函数:

def func1(s: set, f: Callable) -> Callable:
    def func2(x: int) -> dict:
        while x:
            s = s - {x}
            x = f(x)
        return s
    return func2

f2 = func1({1,2,3,4}, lambda x: x-1)

如果我尝试,我会得到与该语句相关的错误。我不明白为什么它不是范围的一部分,因为我认为它在被调用创建时是固定的。f2(3)"local variable 's' referenced before assignment"s = s - {x}sfunc1f2

我能够通过使用这种方法来解决这个问题:我将所有参数组合到一个函数中,说并使用该操作,该操作的行为符合预期:func3functools.partial

from functools import partial
def func3(x: int, s: set, f: Callable) -> dict:
    while x:
        s = s - {x}
        x = f(x)
    return s

f2 = partial(func3, s={1,2,3,4}, f=lambda x: x-1)

当我打电话时,我得到了预期的。f2(3){4}

我的理解是,这两种方法应该产生相同的结果;但是,我显然遗漏了关于可变范围在第一种情况下如何运作的东西。任何见解将不胜感激。

python-3.x 函数 函数编程 闭包

评论

0赞 Kelly Bundy 1/22/2022
这回答了你的问题吗?Python 3:UnboundLocalError:赋值前引用的局部变量
0赞 Kelly Bundy 1/22/2022
你期望什么输出?print(f2(2), f2(3), f2(2))

答:

2赞 Frank Yellin 1/22/2022 #1

你的第一段代码的问题是里面有一个局部变量。它与你在 中定义的变量没有联系。请记住,在函数中分配给的任何变量都是局部变量,除非您另有声明。sfunc2sfunc1

解决方法是将 添加到您的定义中。然后 Python 会意识到 inside 所指的和 inside 是一样的。nonlocal sfunc2sfunc2sfunc1

@KellyBundy指出,这可能仍然不能给你你想要的东西。如果你只是简单地做非局部变量,你实际上是在说这两个变量指向同一个集合。所做的任何更改都是“永久性的”。第二次被调用,will 的值是第一次被调用结束时的任何值。目前尚不确定这是否是预期的。ssf2sf2

如果想在每次调用时都复位,则需要将两者分开。最简单的方法是从 开始,然后在 sfunc2s0func2' 中使用,可以根据需要进行修改。sf2sfunc2s0 = ss0func2. Since is never modified within, it refers to the outer variable. And you have a different variable within

评论

0赞 Kelly Bundy 1/22/2022
不过,这并不等同于他们的版本。不清楚他们真正想要的是什么。nonlocalpartial
0赞 Frank Yellin 1/22/2022
@KellyBundy。不知道你的意思。两者都返回相同的答案。两者都在变量上闭合,但使用不同的语法来这样做。我敢肯定,在内部,它们非常不同。s
0赞 Kelly Bundy 1/22/2022
鉴于他们标记了,其描述甚至说“避免副作用”,我倾向于怀疑这不是他们想要的。functional-programming
0赞 Kelly Bundy 1/22/2022
尝试使用他们的解决方案,并按照您的建议修复解决方案。print(f2(2), f2(3), f2(2))partial
0赞 Frank Yellin 1/22/2022
文本中的具体问题是“我不明白为什么不在范围内”。我向他们解释了它,并向他们展示了如何解决它。s