Это не очень Pythonic, но если вы действительно должны:
import inspect
def compact(*names):
caller = inspect.stack()[1][0] # caller of compact()
vars = {}
for n in names:
if n in caller.f_locals:
vars[n] = caller.f_locals[n]
elif n in caller.f_globals:
vars[n] = caller.f_globals[n]
return vars
def extract(vars):
caller = inspect.stack()[1][0] # caller of extract()
for n, v in vars.items():
caller.f_locals[n] = v # NEVER DO THIS - not guaranteed to work
Я довольно часто использовал эти реализации, и они работают, но техническая модификация f_locals
не поддерживается.
Если серьезно, если вы действительно чувствуете необходимость использовать эти функции, вы, вероятно, делаете что-то неправильно. Кажется, он противоречит философии Python как минимум по трем причинам: «явный лучше, чем неявный», «простой лучше, чем сложный», «если реализацию трудно объяснить, это плохая идея», возможно больше (и действительно, если у вас достаточно опыта в Python, вы знаете, что такие вещи просто не сделаны). Я мог бы увидеть, что это полезно для отладчика или анализа после смерти, или, возможно, для какой-то очень общей структуры, которая часто должна создавать переменные с динамически выбранными именами и значениями, но это растяжение.
Если вы собираетесь использовать эти функции, вы должны по крайней мере хранить переменные extract
, содержащиеся в небольших областях. Оберните их в функции, которые вы можете затем считать «черными ящиками». Основная причина extract
плохая в том, что она помещает переменные в вашу таблицу символов таким образом, который непонятен при проверке кода. Если вы сохраните влияние этих переменных на очень маленькую функцию и объясните, что вы делаете, с помощью чистого кода и комментариев, это не такая уж большая проблема.