NB: этот вопрос предполагает Python 2.7.3.
Я ищу разумный подход к динамическому изменению локального пространства имен функции, желательно таким образом, чтобы добавить наименьший беспорядок в функцию тела.
То, что я имею в виду, будет выглядеть примерно так:
import os
from namespace_updater import update_locals
def somefunc(x, y, z):
# ...
# ...
# this and that
# ...
# ...
if os.environ.get('FROBNICATE'):
from frobnitz import frobnicate
update_locals(frobnicate(locals()))
#
# life goes on, possibly with duly frobnicated local variables...
# ...
# ...
# ...
Спасибо!
PS: Ниже приведены подходы, которые не работают.
Самый наивный подход к этому был бы примерно таким:
locals().update(new_locals(locals())
... но документация для locals()
очень четко предостерегает от использования такого колдовства для измените локальные переменные, поэтому, пожалуйста, не отправляйте это как ответ (если только вы не можете привести отличный аргумент в пользу игнорирования предупреждения документации).
Далее по шкале наивности что-то вроде
for k, v in new_locals(locals()).items():
exec ('%s = v' % k)
AFAICT, такой код не может быть "в стороне" (т. е. он должен находиться в теле функции), что не идеально. Но настоящим препятствием является то, что exec ('%s = v' % k)
хак может привести к некоторым причудливым ошибкам.
Когда я пишу «причудливые ошибки», я имею в виду «ошибки, которые кажутся странными для кого-то с таким слабым пониманием exec ('%s = v' % k)
, как у меня». Насколько слабо я понимаю этот хак? Чтобы ответить на этот вопрос, рассмотрим сценарий ниже. Он имеет три варианта: (1) точно такой, как показано; (2) после удаления начального #
строки 18; (3) после удаления первых #
в обеих строках 15 и 18 (т.е. для этого варианта код не закомментирован). Я не мог предсказать поведение вариантов (2) и (3) этого скрипта. Я даже не смог бы с уверенностью более 50% предсказать поведение варианта (1). Вот как слабо я понимаю exec ('%s = v' % k)
хак. Если вы не можете уверенно и правильно предсказать, как поведут себя три варианта этого скрипта (под Python 2.7), можно с уверенностью сказать, что ваше понимание ситуации примерно такое же слабое, как и мое, и вам, вероятно, тоже следует держаться подальше от exec ('%s = v' % k)
.
x = 'global x' # 01
y = 'global y' # 02
def main(): # 03
x = 'local x' # 04
y = 'local y' # 05
run(locals()) # 06
print 'OK' # 07
return 0 # 08
# 09
def run(namespace): # 10
global y # 11
print locals().keys() # 12
for k, v in namespace.items(): # 13
print '%s <- %r' % (k, v) # 14
exec ('%s = v' % k) #in locals() # 15
print locals().keys() # 16
x = x # 17
#z = lambda: k # 18
print x # 19
print y # 20
# 21
exit(main()) # 22
exec
), но это не будет хорошим решением и, возможно, даже специфичным для реализации. Хорошее решение будет учитывать проблему, которую вы не описали. По моему опыту, SO не очень хорошо подходит для таких вопросов, поэтому, возможно, это действительно еще один случай Проблема XY. - person Niklas B.   schedule 08.05.2012