Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 21, 2012 23:59:38

fata1ex
От:
Зарегистрирован: 2009-07-11
Сообщения: 732
Репутация: +  52  -
Профиль   Отправить e-mail  

Не могу разобраться - почему работает неправильно.

vault, вся информация есть в ссылках. Без английского не куда ) В общем, ответ-то угадался сразу - во всём виновато позднее связывание, но с такой проблемой я не встречался.

Еще интересно, что:

>>> fab_adders = lambda a, b: (lambda x: x + off for off in xrange(a, b + 1))
>>> for adder in list(fab_adders(0, 5)):
...     print adder(0)
...     
... 
5
5
5
5
5
5

А ответ должен быть такой:
>>> fab_adders = lambda a, b: [lambda x, off=off: x + off for off in xrange(a, b + 1)]
>>> for adder in fab_adders(0, 5):
...     print adder(0)
...     
... 
0
1
2
3
4
5



Отредактировано fata1ex (Июнь 22, 2012 00:11:37)

Офлайн

#2 Июнь 22, 2012 02:59:55

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10010
Репутация: +  857  -
Профиль   Отправить e-mail  

Не могу разобраться - почему работает неправильно.

Офлайн

#3 Июнь 22, 2012 07:13:48

sp3
От:
Зарегистрирован: 2010-01-12
Сообщения: 405
Репутация: +  18  -
Профиль   Отправить e-mail  

Не могу разобраться - почему работает неправильно.

>>> def gen(a,b):
... 	lst = []
... 	for i in xrange(a,b+1):
... 		lst.append(lambda x: x+i) # здесь i переменная из верхней функции
... 	return lst
... 
... for k in gen(1,3):
...     print k(1)
4
4
4
>>> def gen(a,b):
... 	lst = []
... 	for i in xrange(a,b+1):
... 		lst.append(lambda x, i=i: x+i) # а здесь локальная, для каждой лямбды своя
... 	return lst
... 
... for k in gen(1,3):
...     print k(1)
2
3
4
здесь как бы срабатывает правило E из LEGB (слышали о таком?)



Офлайн

#4 Июнь 22, 2012 10:00:01

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10010
Репутация: +  857  -
Профиль   Отправить e-mail  

Не могу разобраться - почему работает неправильно.

>> def gen(a,b):
...     lst = []
...     for i in range(a, b + 1):
...         lst.append(lambda x, i=i: x + i)
...     return lst
... 
>>> lst = gen(0, 5)
>>> lst[0](5)
5
>>> lst[1](5)
6
>>> lst[1](5, 4)
9
>>> 
у функции меняется количество аргументов



Офлайн

#5 Июнь 22, 2012 10:39:22

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

Не могу разобраться - почему работает неправильно.

Решение очевидно.
Непонятки с лямбдой возникают из-за непонимания того, что после завершения цикла, в i хранится значение последней иттерации

for i in range(0, 10):
  pass
print i
>>> 9

Поэтому нужно, чтобы на момент вычисления значения лямбды, i имело нужное значение, то есть цикл еще не закончился.

def gen(a,b):
        for i in range(a, b+1):
	    yield lambda x: x+i
for func in gen(1,3):
  print func(5)



Офлайн

#6 Июнь 22, 2012 10:40:43

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

Не могу разобраться - почему работает неправильно.

ИМХО самое питонячее решение



Офлайн

#7 Июнь 22, 2012 11:16:11

fata1ex
От:
Зарегистрирован: 2009-07-11
Сообщения: 732
Репутация: +  52  -
Профиль   Отправить e-mail  

Не могу разобраться - почему работает неправильно.

FishHook, в задании требовался список :) да писали уже такое решение…скажем…в посте #2

py.user.next, это да. И что же делать? )



Отредактировано fata1ex (Июнь 22, 2012 11:27:49)

Офлайн

#8 Июнь 22, 2012 11:46:26

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

Не могу разобраться - почему работает неправильно.

fata1ex
да писали уже такое решение
Блин, я думал сам придумал



Офлайн

#9 Июнь 22, 2012 11:47:08

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

Не могу разобраться - почему работает неправильно.

fata1ex
в задании требовался список
Эээ? напомните задание, пжлст.



Офлайн

#10 Июнь 22, 2012 11:51:21

fata1ex
От:
Зарегистрирован: 2009-07-11
Сообщения: 732
Репутация: +  52  -
Профиль   Отправить e-mail  

Не могу разобраться - почему работает неправильно.

Можно сделать так:

>>> from functools import partial
>>> fab_adders = lambda a, b: [partial(lambda x, off: x + off, off=off) for off in xrange(a, b + 1)]
>>> for adder in fab_adders(0, 5):
...     print adder(0)
... 
0
1
2
3
4
5
>>> for adder in fab_adders(0, 5):
...     print adder(0), adder(0, 2)
... 
0
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: <lambda>() got multiple values for keyword argument 'off'
Плюс добавить плюшечку, чтобы при вызове adder со вторым аргументом интерпретатор ругался правильно.

FishHook, задание в первом посте :)



Отредактировано fata1ex (Июнь 22, 2012 11:53:17)

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version