python 3.1 не разобрался с lambda
Какая у тебя версия python?
3.1
Не уверен, имеет ли это отношение к -классности функций, но переменные из внешних неглобальных областей в кложуры попадают не по значению, а по ссылке. А х - это одна переменная, которая последовательно пробегает разные значения.
3.1У меня на 2.x давала runtime error, поскольку внутрь mapper-а шла сама lambda (похоже на убогую реализацию list comprehensions)
А х - это одна переменная, которая последовательно пробегает разные значения.ясно, а как сделать то, что я хочу? (то бишь передать по значению тем или иным путём). Какой путь pythonic-way?
closures = map(lambda x: lambda: mapper(x lst)
тогда уж можно заюзать другую стороннюю тулзу:
closures = [ partial(mapper,x) for x in lst ]
update:
(похоже на убогую реализацию list comprehensions)а видимо ты прав. Причём убогость не искоренили полностью даже в третей версии
lamlam = [ (lambda x: lambda: mapper(xx) for x in lst ]
в очередной раз убеждаюсь, что понятие "интуитивно понятный язык" некорректно. Сколько таких не анонсировалось, а везде свои загоны
неужель попроще нильзя?
дачот ваще жесть какаяточтобы выглядело проще можно использовать функцию partial из библиотеки functools. Она создаст объект, в котором будет хранить ссылку на оригинальную функцию и список аргументов.
В общем-то, смысл в том, что обращение по ссылке происходит в момент выполнения лямбды, а не при создании. А вот в C++0x-шных лямбдах, кстати, способ доступа к внешним переменным прописываются в заголовке.
в очередной раз убеждаюсь, что понятие "интуитивно понятный язык" некорректно. Сколько таких не анонсировалось, а везде свои загоныа то
читай и наслаждайся бояном:
http://wiki.python.org/moin/PythonWarts
Если заменить второй принт на
print ([y for y in closures]), то в 2.6.4 тоже всё начинает работать. Ну то есть печатать 16 много раз. Видимо, у них утекают переменные из компрехенжена во внешний scope. Поэтому все вхождения слова x на самом деле реферят одну и ту же переменную, поэтому происходит фигня. В 3.х, видимо, пофиксили это, но не до конца: теперь переменная компрехенжена живёт в скоупе компрехенжена, но по-прежнему одна на весь скоуп.
А разгадка одна — в Питоне переменные объявляются присваиванием, поэтому scopes ущербны донельзя.
В сишарпе, кстати, та же проблема у обычного foreach, и за это их совсем простить нельзя. В смысле что `foreach (var v in x) embedded-statement` согласно спецификации раскрывается в
{
E e = Cx.GetEnumerator;
try {
V v;
while (e.MoveNext {
v = (VT)e.Current;
embedded-statement
}
}
finally {
… // Dispose e
}
}
Если бы они написали V v = (VT)e.Current;, объявив переменную прямо во внутреннем скоупе, всё было бы отлично, а так она получается общая, соответственно все захватывающие её лямбды захватывают одну и ту же. Причём они об этом знают, но не исправляют, потому что "breaking change" и бла бла бла, причём я даже не уверен, что они хотя бы в четвёртом шарпе это сделают ошибкой (потому что специально это НИКТО НИКОГДА не напишет чтобы исправить в каком-нибудь пятом. Причём в LINQ всё работает правильно!
Видимо, у них утекают переменные из компрехенжена во внешний scope. Поэтому все вхождения слова x на самом деле реферят одну и ту же переменную, поэтому происходит фигня. В 3.х, видимо, пофиксили этону, это известная весчь
http://docs.python.org/dev/3.0/whatsnew/3.0.html#changed-syn...
(предпоследний абзац)
но не до конца: теперь переменная компрехенжена живёт в скоупе компрехенжена, но по-прежнему одна на весь скоуп.имхо, вполне ожидаемое поведение.
создавать свой словарь на каждую итерацию цикла — это вообще разврат, итак питоньи оптимизаторы плачут кровавыми слезами
print ([y for y in closures])у меня в 2.5.4 эта конструкция вообще не работает
>>> items = [0, 1, 2]
>>> it = [(lambda : x*x) for x in items]
>>> it
[<function <lambda> at 0x5f1b18>, <function <lambda> at 0x5f1de8>, <function <lambda> at 0x5f1e60>]
>>> [x for x in it]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for *: 'function' and 'function'
причем в 2.5.4 вот такое работает
>>> it[0]
4
а в 2.5.1 даж это не работает
>>> it[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for *: 'function' and 'function'
сказано же, заменить в последнем случае x на y =)
>>> items = [0, 1, 2]
>>> it = [(lambda : x*x) for x in items]
>>> [y for y in it]
[4, 4, 4]
> а в 2.5.1 даж это не работает
не верю!
напиши в _чистом_ интерпретаторе этот код (без [x for x in it]) и всё будет в порядке
не верю!о блин
когда с иксами пишешь то оно каким-то макаром ломает массив и после этого всё перестает работать
>>> items = [0, 1, 2]
>>> it = [(lambda : x*x) for x in items]
>>> [y for y in it]
[4, 4, 4]
>>> it[0]
4
>>> [x for x in it]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for *: 'function' and 'function'
>>> [y for y in it]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for *: 'function' and 'function'
>>> it[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for *: 'function' and 'function'
он в x записывает функцию, после чего всё "ломается":
In [1]: items = [0, 1, 2]
In [2]: it = [(lambda : x*x) for x in items]
In [3]: type(x)
Out[3]: <type 'int'>
In [4]: [x for x in it]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
C:\Users\vj\<ipython console> in <module>
C:\Users\vj\<ipython console> in <lambda>
TypeError: unsupported operand type(s) for *: 'function' and 'function'
In [5]: type(x)
Out[5]: <type 'function'>
Оставить комментарий
yroslavasako
Есть простой вопрос для тех, кто питон практикует, но для новичка, только прочитавшего туториал он сложен и не понятен.Почему код
выдаёт
Оба варианта казалось бы должны давать одинаковый результат. Чего я не учёл? Или в питоне функции тоже не первоклассные объекты, а, скажем так, полтораклассные?