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

时间:2019-05-30 01:01:10

标签: python closures python-decorators scoping

在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的值?也就是说,我希望x中的foo绑定到外部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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

  public render(): JSX.Element {
    // tslint:disable:jsx-no-lambda
    return (
      <div style={{ padding: '2px' }}>

        <TextField          
          label="Url"          
          onGetErrorMessage={this._checkIfValid}
        />
      </div>
    );
  }

  private _checkIfValid(value: string) {    
    const regex = new Regexp(/^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/, 'g');
    return regex.test(value);
  }

与最初的解决方案保持一致,您也可以做类似的事情。

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)。