Классические подвохи: итерация, поздняя привязка, деление
Подборка «вопросов с подвохом», которые любят давать, чтобы проверить внимательность.
Эти ошибки выглядят безобидно, компилируются и часто дают неправильный, но не падающий результат — самый коварный вид багов.
Подвох 1: изменение списка во время итерации
Чёткий ответ. Удалять элементы из списка, по которому идёт for, нельзя: индексы сдвигаются, и цикл пропускает элементы. Решение — итерировать по копии (list[:]) или строить новый список.
nums = [1, 2, 2, 3]
for n in nums:
if n == 2:
nums.remove(n) # меняем список во время итерации
print("неверно:", nums) # одна двойка осталась!
nums = [1, 2, 2, 3]
result = [n for n in nums if n != 2] # правильный способ
print("верно: ", result)
Вывод:
неверно: [1, 2, 3] верно: [1, 3]
После удаления первой двойки индексы сдвинулись, и цикл «перепрыгнул» вторую — она уцелела. Comprehension строит новый список и проблемы не имеет.
Подвох 2: поздняя привязка в замыканиях
Лямбды в цикле не запоминают текущее значение переменной — они захватывают саму переменную и читают её значение в момент вызова, когда цикл уже закончился.
funcs = [lambda: i for i in range(3)]
print("ловушка:", [f() for f in funcs]) # ожидали 0,1,2
funcs = [lambda i=i: i for i in range(3)] # фиксируем через дефолт
print("фикс: ", [f() for f in funcs])
Вывод:
ловушка: [2, 2, 2] фикс: [0, 1, 2]
Все три лямбды смотрят на одну переменную i, которая после цикла равна 2. Приём i=i сохраняет текущее значение в аргументе по умолчанию (он вычисляется сразу).
Подвох 3: целочисленное деление и остаток
/ всегда даёт float, // — целочисленное деление с округлением вниз (к меньшему), а не к нулю. Для отрицательных чисел это сюрприз.
print(7 / 2) # обычное деление -> float
print(7 // 2) # floor division
print(-7 // 2) # округление ВНИЗ, не к нулю -> -4
print(-7 % 2) # остаток того же знака, что делитель
Вывод:
3.5 3 -4 1
Итог
- Не меняйте список во время
forпо нему — итерируйте по копии или стройте новый. - Лямбды в цикле захватывают переменную, а не значение; фиксируйте через
x=x. //округляет вниз (для отрицательных-7 // 2 == -4);/всегда float.