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 не очень хочется по вопросам производительности.