В приведённом на Python примере с потоками: for i in range(10): threading.Thread(target=lambda: print(i)).start() объясните, почему вывод может быть неожиданным и как исправить код для корректного поведения

17 Мар в 08:46
15 +1
0
Ответы
1
Проблема: лямбда в коде захватывает внешнюю переменную iii по ссылке, а не её текущее значение. Потоки обычно стартуют позже, когда цикл уже завершён и iii равно конечному значению (обычно 101010), поэтому вывод будет неожиданным (например, десять раз 101010) или вообще непредсказуемым.
Почему: в Python замыкания используют ссылку на переменную, а не копию её значения. Поток выполняет `print(i)` уже после того, как значение iii могло измениться.
Как исправить (варианты):
1) Зафиксировать значение через аргумент по умолчанию:
for i in range(101010):
threading.Thread(target=lambda i=i: print(i)).start()
2) Передавать аргумент через `args` (или `kwargs`):
for i in range(101010):
threading.Thread(target=print, args=(i,)).start()
3) Использовать явную функцию с параметром:
def worker(x):
print(x)
for i in range(101010):
threading.Thread(target=worker, args=(i,)).start()
Дополнительно: если нужно дождаться завершения всех потоков, храните объекты потоков и сделайте `join()`:
threads = []
for i in range(101010):
t = threading.Thread(target=print, args=(i,))
t.start()
threads.append(t)
for t in threads:
t.join()
Любой из первых трёх вариантов гарантирует, что каждый поток выведет своё корректное значение iii.
17 Мар в 09:41
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир