Как заставить функции Python связывать вмещающую переменную со значением, а не с именем - PullRequest
2 голосов
/ 30 мая 2019

В функциях 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 ]

3 голосов
/ 30 мая 2019

Вы также можете воспользоваться аргументом по умолчанию:

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

x=10
print(foo(1)) # prints 2
x=11
print(foo(1)) # prints 2
0 голосов
/ 30 мая 2019

Используйте functools.partial , чтобы применить первый аргумент и получить новую функцию, принимающую один аргумент.Я решил не украшать функцию добавления, поскольку она очень общая и полезная в других местах.

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

...