如何使 python 函数将封闭变量绑定到值而不是名称

How to make python functions bind enclosing variable to value rather than to name

在 python 函数中,从封闭范围引用变量是完全合法的。这些变量指的是调用函数时它们拥有的任何值。所以,例如

x = 1 # unused
def foo(y):
    return x+y

x=10
print(foo(1)) # prints 11
x=11
print(foo(1)) # prints 12

是否可以将变量 x 冻结为创建时 x 的任何值?也就是说,我希望 foo 中的 x 绑定到外部 x 的值而不是它的名称。基本上我想要的行为是

x = 1
def foo(y):
    return 1+y # I'd rather not hard code the value of x here

x=10
print(foo(1)) # prints 2
x=11
print(foo(1)) # prints 2

我目前有一个可行的解决方案,但它的可读性不是很好,我认为可能会有更好的解决方案(也许是装饰器?)

我的解决方案

x = 1
def wrapper():
    local_x = x
    def foo(y):
        return local_x+y
    return foo
foo = wrapper()

x=10
print(foo(1)) # prints 2
x=11
print(foo(1)) # prints 2

您还可以利用默认参数:

x = 1
def foo(y, x=x):
    return x + y

x=10
print(foo(1)) # prints 2
x=11
print(foo(1)) # prints 2

使用functools.partial应用第一个参数并得到一个接受一个参数的新函数。我选择不装饰 add 函数,因为它很通用,在其他地方也很有用。

from functools import partial
from operator import add       # does same thing as your foo

x = 1
foo = partial(add, x)
print(foo(1)) # prints 2

x = 11

print(foo(1)) # prints 2

为了与您原来的解决方案保持一致,您还可以执行类似的操作。

def wrapper(localx):
    def foo(y):
        return localx + y
    return foo

foo2 = wrapper(x)
print(foo2(1)) # prints 12

请注意,现在减少了对全局的依赖,您甚至可以将文字值传递给 wrapper(例如 foo3 = wrapper(5))。