LINUX.ORG.RU

Ответ на: комментарий от aedeph_
[[lambda x, i=i: x*i for i in 1,2,3][i](1) for i in 0,1,2]

(оставим лишние скобочки лиспу)

неновичёк эту особенность должен знать, новичёк пусть наслаждается своим джедайством (сам я не сразу распарсил :)

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Какую особенность? Без скобок в py3 синтаксическая ошибка, в py2 со скобками или без list index is out of range. Со скобками в py3 вывод [1, 2, 3], как и положено, если я правильно распарсил это говно.

Собственно, что этот код делать-то должен?

anonymous
()
Ответ на: комментарий от Virtuos86

неновичёк эту особенность должен знать

Это не особенность, это определенно баг во втором питоне. При использовании i=i, функция должна ловить значение переменной i, внешней по отношению к функции, что и можно видеть например тут:

flst = [lambda x, i=i: x*i for i in 1,2,3]
print [flst[i](1) for i in 0,1,2]
Но в двойном list comprehension с одинаковым счетчиком второй питон почему-то не осиливает. Впрочем, никто в здравом уме не будет писать такой код.

anonymous
()
Ответ на: комментарий от anonymous

Собственно, что этот код делать-то должен?

там два цикла, а счётчик один — переменная «i». А в Python переменные цикла for и list comprehensions глобальны для неймспейса, в котором определены. Поэтому i здесь будет меняться в обоих циклах.

На каждую итерацию цикла

    for i in 0,1,2
выполняется (по сути вложенный) цикл
    for i in 1,2,3
Но фигня в том, что индекс результирующего списка этого вложенного цикла -

«[ i ]»

- берётся на основании первого цикла (то есть ага, i будет принимать значения 0,1,2), который в душе не подозревает, что i поменялась где-то там ещё.

Отсюда правило не использовать одну переменную-счётчик в нескольких циклах одновременно.

Virtuos86 ★★★★★
()
Ответ на: комментарий от anonymous

жаль, что без скобок ошибка, очередное «улучшение» третьепитона :(

Virtuos86 ★★★★★
()
Ответ на: комментарий от anonymous

ты не прав, анонимный брат. Это разве что баг дизайна языка.

Вся эта мифическая ерундень развернётся в такой код:

res = []
for i in (0,1,2):
    # здесь i или 0, или 1, или 2
    lst = []
    for i in (1,2,3):
        # здесь i уже или 1, или 2, или 3, поскольку меняется вложенным циклом
        lst.append(lambda x, i=i: x*i) # здесь аргумент по умолчанию i принимает значение "внешней" i, и это одно из (1,2,3), а не из (0,1,2)
     res.append(lst[i](1)) # а здесь в лучшем случае сразу произойдёт фейл, потому что гладиолус; в худшем -- что-то насчитается

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

- берётся на основании первого цикла (то есть ага, i будет принимать значения 0,1,2)

Это не так, list index out of range как раз говорит о том, что i принимает значения вложенного цикла 1, 2, 3. Скорее так происходит, i становится 0 из внешного цикла, потом проходит 1, 2, 3 по внутреннему, по окончанию внутреннего, из списка пытается выбрать 4ый (3) элемент, которого нет. Потом i снова становится 1 из-за внешнего цикла.

Но я не о том, а вот о чем:

# ipython3 test.py -- правильный вывод, значение i словилось
[0, 1, 2]
[0, 1, 2]
# ipython test.py -- неправильный вывод, значение не словилось, словилась сама i
[2, 2, 2]
[0, 1, 2]
# cat test.py 
flst = [lambda x, i=i: x*i for i in (0,1,2)] 
print([[lambda x, i=i: x*i for i in (0,1,2)][i](1) for i in (0,1,2)])
print([flst[i](1) for i in (0,1,2)])

anonymous
()
Ответ на: комментарий от Virtuos86

Хотя да, ты прав, с ловлей значений все окей.

anonymous
()

Выводит где-то 200 сущностей с 'x' по 'yz'. Но from 'a' to 'y' работает правильно.

ну а что ты хотел-то? С чего ты взял, что

$i = 'z'
$i++
будет БОЛЬШЕ чем 'z'? Будет таки 'aa', что вполне естественно и документировано. А вот 'aa' таки МЕНЬШЕ чем 'z'.

ЗЫЖ быдлокодеры, такие быдлокодеры...

drBatty ★★
()

ещё смешнее то, что

for($i = 'а'; $i <= 'я'; $i++)
	echo "$i\n";
сваливается в бесконечный цикл (тут 'а' русская)

drBatty ★★
()
Ответ на: комментарий от anonymous

(то есть
ага, i будет принимать
значения 0,1,2)


вообще-то я описал ход мыслей человека, который думает, что это будет работать; сам я так ни разу не думаю :)

Да, похоже на багу, хм.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

«Бага» только в том, что внешний цикл не восстанавливает свой счетчик после внутреннего, но это окей поведение вообще говоря.

anonymous
()
Ответ на: комментарий от Virtuos86

Анонимус меня запутал, никакого бага нет.
Единственный баг - невнимательность, но он по другую сторону монитора гнездится.

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Анонимус меня запутал, никакого бага нет.

:3

Но в третьем питоне таки лучше поведение, list comprehension не трогает внешние переменные без необходимости.

anonymous
()
Ответ на: комментарий от anonymous

Это pythonic подход просто - всё работает чисто на соглашении (не ломать это). К третьей версии убедились, что не везде этого достаточно и позволительно :-).

Virtuos86 ★★★★★
()
Ответ на: комментарий от anonymous

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

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Да пофигу, мне никогда не мешало такое поведение. Плюс мне почему-то никогда не приходило в голову использовать счетчики с одинаковыми названиями, тем более во вложенных list comprehension (как оно по-русски зовется?).

anonymous
()
Ответ на: комментарий от anonymous

Никто не знает, я встречал несколько вариантов разной степени удачности: списковые (списочные?) включения, списковые встраивания, генераторы списков

Virtuos86 ★★★★★
()

То, что оно ведет себя не так, как хотелось бы чтобы вел себя нормальный язык - это понятно. Но как понять тех программистов, которые аналогом этого примера дают проход по списку? А если кодировка UTF-32 и вместо 'z' какой-нибудь символ из конца таблицы, то ничего, что список может 15 гигабайт ОЗУ занять?

Tark ★★
()
Ответ на: комментарий от anonymous

Ну PHP очевидно быдлоподелка. А Perl был хорош для своего времени (когда он быль альтернативой писанию на баше) но сейчас явно устарел и даже хуже PHP. Много видел Perl скриптов которые НЕВОЗМОЖНО ПРОЧИТАТЬ, и при изменении кода в одном месте ломается всё где только возможно и даже где казалось бы даже не возможно.

tyler19
()
Ответ на: комментарий от Tark

То, что оно ведет себя не так, как хотелось бы чтобы вел себя нормальный язык - это понятно. Но как понять тех программистов, которые аналогом этого примера дают проход по списку? А если кодировка UTF-32 и вместо 'z' какой-нибудь символ из конца таблицы, то ничего, что список может 15 гигабайт ОЗУ занять?

обожаю тебя мой не анонимный друг.

все перлы-фанаты сразу покраснели, прочитав:-)

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.