[python] eval не видит locals в list comprehension
От: Кодт Россия  
Дата: 05.04.23 12:32
Оценка: 6 (1)
eval('[0 for a in A for b in B]', None, {'A':[1,2,3], 'B':[4,5,6]})
eval('[0 for a in A if B]',       None, {'A':[1,2,3], 'B':True})

В обоих случаях переменная A загружается как LOAD_NAME, а B — как LOAD_GLOBAL, и, естественно, приводит к ошибке.

Вопрос: можно ли это как-то исправить?

Есть лайфхак — затащить нужные переменные внутрь цикла — тогда генератор первого уровня возьмёт A,B как LOAD_NAME, а дальше он со своими внутренними переменными управится корректно (LOAD_FAST)
eval('[0 for _A,_B in [(A,B)] for a in _A for b in _B]', None, {'A':[1,2,3], 'B':[4,5,6]})

или через лямбду (LOAD_DEREF)
eval('(lambda _A,_B: [0 for a in _A for b in _B])(A,B)', None, {'A':[1,2,3], 'B':[4,5,6]})

Но код при этом становится грязным.

Подмешивать locals в globals не очень хочется по вопросам производительности.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.