Как определить список непостоянных функций в al oop с лямбда-функциями? - PullRequest
0 голосов
/ 22 апреля 2020

Допустим, я хочу создать список функций funclist, чтобы функции этого списка вели себя так:

funclist[0](x) = 0
funclist[1](x) = x
funclist[2](x) = 2*x
funclist[3](x) = 3*x

Предполагая, что список слишком длинный (скажем, размера 100 ), чтобы определить эти функции один за другим, естественный способ написать это будет:

funclist = []
for k in range(100):
    f = lambda x: k*x
    funclist.append(f)

Проблема в том, что этот подход не работает, потому что Python интерпретирует локальные переменные внутри определения функций. Это проблема, с которой я часто сталкивался на этом сайте, например здесь или здесь . К сожалению, эти пользователи хотят определить функции constant , поэтому предлагаемое решение (то есть определение локальной копии итерируемой переменной k) не работает для меня (это также то же решение, предложенное в Python FAQ ). Например, следующий синтаксис не работает:

funclist = []
for k in range(100):
    f = lambda local_k=k, x: local_k*x
    funclist.append(f)

Я нашел следующее решение:

funclist = []
for k in range(10):
    def f(x, product_factor=k): return x*product_factor
    funclist.append(f)

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

from functools import partial 

def product(x,product_factor): return x*product_factor
funclist = []
for k in range(10):
    funclist.append( partial(product, product_factor=k) )

Поэтому мой вопрос: есть ли способ достичь этого результата только с помощью лямбда-функций? Или тот факт, что у меня есть «движущийся параметр», обрекает меня на то или иное определение функции двух переменных? Позвольте мне уточнить, что я спрашиваю об этом, потому что я пытаюсь лучше понять, как функции и карри работают в Python.

Ответы [ 2 ]

1 голос
/ 22 апреля 2020

Первоначальная проблема заключается в том, что k вычислялось только один раз в конце l oop, тогда как здесь создание функции, вызов get_function, каждый раз запускает оценку k.

Конечно, ваше решение с аргументом по умолчанию также работает, по-видимому, это наиболее распространенное решение для этой проблемы

Теперь вы сказали, что оно не работает с lamdba, просто потому, что вы поставили первый аргумент по умолчанию:

funclist = []
for k in range(100):
    f = lambda  x, local_k=k,: local_k*x
    funclist.append(f)


print(funclist[10](3)) #30
print(funclist[99](3)) # 297
print(funclist[0](3)) # 0

работает просто отлично

1 голос
/ 22 апреля 2020

Ваш лямбда-подход не работает, потому что у вас есть ключевой аргумент перед позиционным. Просто измените порядок, как вы это сделали в рабочих решениях:

funclist = [(lambda x, local_k=k: local_k*x) for k in range(100)]

>>> funclist[3](8)
24
>>> funclist[5](9)
45
...