@PesyCorm

Почему в данном примере запуска потока с переданным аргументом, есть разница между способом передачи аргумента?

Привет
Наткнулся на странное, а точнее непонятное мне, поведение при запуске потока.
Почему из приведенных трех примеров, способ запуска потока (пример 1), где потоки добавлялись в список и аргумент передавался в метод сразу, а не через kwargs, работает не так как ожидается? При этом, если использовать вместо списка словарь, то: при итерации по словарю через items код работает ожидаемо (пример 2), а если итерироваться с помощью values (пример 3), то работает аналогично примеру 1 - т.е., не так как ожидалось.
# Общий код
import threading

def print_i(i):
    print(i)

Пример 1

threads = []
for i in range(2):
    threads.append(threading.Thread(target=lambda: print_i(i)))

for t in threads:
    t.start()

# Вывод в консоль:
1
1


Пример 2

threads = dict()
for i in range(2):
    threads[i] = threading.Thread(target=lambda: print_i(i))

for i, t in threads.items():
    t.start()

# Вывод в консоль:
0
1


Пример 3

threads = dict()
for i in range(2):
    threads[i] = threading.Thread(target=lambda: print_i(i))

for t in threads.values():
    t.start()

# Вывод в консоль:
1
1


Пример 4 (просто корректный способ запуска с передачей аргументов в Thread(**kwargs), который работает ожидаемо

threads = []
for i in range(2):
    threads.append(threading.Thread(target=print_i, kwargs={'i':i}))

for t in threads:
    t.start()

# Вывод в консоль:
0
1


Мне больше даже интересно, связано ли это именно с потоками или может это какая-то особенность самих структур данных?

UPD:
это как-то связано с пространством имен в потоках?
вот пример номер 5 в котором все имена уникальны, то получим опять те самые две единицы
import threading

def print_i(arg):
    print(arg)


threads = dict()
for i in range(2):
    threads[i] = threading.Thread(target=lambda: print_i(i))

for x, t in threads.items():
    t.start()
  • Вопрос задан
  • 39 просмотров
Решения вопроса 1
@dim5x
ЗИ, ИБ.
В любом замыкании в Python переменные связываются по имени.
l = []
for i in range(3):
    l.append(lambda: i)
print([f() for f in l])
>>> [2, 2, 2]


Выход из ситуации — создание отдельной функции или передача аргументов по их имени:
l = []
for i in range(3):
    l.append(lambda i = i : i)
print([f() for f in l])
>>> [0, 1, 2]


Т.е. это не вопрос в потоках.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы