Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 10, 2017 16:54:44

alien308
Зарегистрирован: 2012-06-23
Сообщения: 62
Репутация: +  0  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

Создаю список функций вычисляющих многочлен Лежандра от нулевого до пятого порядка при заданном x.

 from scipy.special import eval_legendre
M0 = 6
f0_l = [lambda x:  eval_legendre(i, x)  for i in range(M0)]
На самом деле вызов
 f0_l[0](0.5)
вычисляет значение полинома Лежандра 5 порядка при аргументе 0.5.
При внимательном рассмотрение оказывается что при выполнении генераторного выражения в области видимости появляется переменная i значением 5. И все элементы списка видят эту переменную и определяют порядок полинома по ней.
Как поправить, чтобы в списке функции просто вычисляли полином с порядком
заданным в генераторном выражении.

Python 2.7.9

Офлайн

#2 Дек. 10, 2017 17:13:24

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

alien308
 [lambda x:  eval_legendre(i, x)  for i in range(M0)]
Вот эта вот херня во втором питоне создает переменные в объемлющем неймспейсе, то есть i из списочного выражения переползает в область видимости функции. С этим сделать ничего нельзя, просто иметь в виду



Отредактировано FishHook (Дек. 10, 2017 17:13:52)

Офлайн

#3 Дек. 10, 2017 19:08:42

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2679
Репутация: +  182  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

От версии питона это не зависит. А происходит очень банальная вещь, lambda-функция получает ссылку на переменную, а не её значение. Как с этим бороться тоже вполне очевидно.

 >>> s = [ lambda x: x+y for y in range(10) ]
>>> [ x(i) for i, x in enumerate(s) ]
[9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
>>> s = [ lambda x, y=y: x+y for y in range(10) ]
>>> [ x(i) for i, x in enumerate(s) ]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#4 Дек. 10, 2017 20:44:46

alien308
Зарегистрирован: 2012-06-23
Сообщения: 62
Репутация: +  0  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

Спасибо, заработало!

Офлайн

#5 Дек. 11, 2017 05:00:04

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

Rodegast
От версии питона это не зависит.
Еще как зависит, в третьем пофиксили

второй
 [x for x in range(10)]
print(x)
>>>9

третий
 [x for x in range(10)]
print(x)
Traceback (most recent call last):
  File "/Users/asmirnov/PycharmProjects/test/test.py", line 5, in <module>
    print(x)
NameError: name 'x' is not defined



Офлайн

#6 Дек. 11, 2017 09:59:03

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2679
Репутация: +  182  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

> Еще как зависит, в третьем пофиксили

 rodegast@rodegast:~$ python3
Python 3.4.2 (default, Oct  8 2014, 10:45:20) 
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> s = [ lambda x: x+y for y in range(10) ]
>>> [ x(i) for i, x in enumerate(s) ]
[9, 10, 11, 12, 13, 14, 15, 16, 17, 18]



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#7 Дек. 11, 2017 10:11:00

Slow
Зарегистрирован: 2017-07-26
Сообщения: 88
Репутация: +  4  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

Rodegast
some strange code

Так у вас замыкание некорректно описано. Естественно, что он замыкает у, но не значение, а ссылку на значение.
Значение по ссылке у вас заменяется в каждой итерации компрехеншна, порождающего s, что изменяет и ранее созданные замыкания (лол, насколько это корректно - это как раз большой вопрос к гвидо)
но после выхода из компрехеншна переменная y определена не будет. посмотрите сами.
Тут вы привели абсолютно некорректный пример.

Отредактировано Slow (Дек. 11, 2017 10:12:34)

Офлайн

#8 Дек. 11, 2017 10:17:23

Slow
Зарегистрирован: 2017-07-26
Сообщения: 88
Репутация: +  4  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

То же самое и у топикстартера. Проблема вообще не в области видимости, а в том, как не надо делать замыкания в питоне.

Офлайн

#9 Дек. 11, 2017 10:19:08

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2679
Репутация: +  182  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

> Так у вас замыкание некорректно описано.

Я то я этого не знаю.

> Тут вы привели абсолютно некорректный пример.

Это иллюстрация того что “от версии питона это не зависит”.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#10 Дек. 11, 2017 10:24:07

Slow
Зарегистрирован: 2017-07-26
Сообщения: 88
Репутация: +  4  -
Профиль   Отправить e-mail  

Генераторное выражение с lambda делает не то

https://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture

тут суть в том, что лямбда - ленивая.
то есть, значение замыкания берется на момент вызова лямбды, а не на момент создания.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version