Python 2.5 имеет эквивалент команды верхнего уровня Tcl?
Есть ли в Python эквивалент команды Tcl верхнего уровня? Для тех, кто не знает, команда "uplevel" позволяет запускать код в контексте вызывающей стороны. Вот как это может выглядеть в python:
def foo():
answer = 0
print "answer is", answer # should print 0
bar()
print "answer is", answer # should print 42
def bar():
uplevel("answer = 42")
Однако это больше, чем просто установка переменных, поэтому я не ищу решение, которое просто изменяет словарь. Я хочу быть в состоянии выполнить любой код.
2 ответа
В общем, то, что вы спрашиваете, невозможно (с результатами, которые вы, несомненно, ожидаете). Например, представьте, что "любой код" x = 23
, Будет ли это добавить новую переменную x
к набору локальных переменных вашего вызывающего, если вы нашли черный магический способ выполнить этот код "в вызывающем"? Нет, не будет - критическая оптимизация, выполняемая компилятором Python, заключается в том, чтобы определить раз и навсегда, когда def
выполняет точный набор локальных переменных (все голые имена, которые присваиваются или иным образом связываются в теле функции), и превращает каждый доступ и установку к этим голым именам в очень быструю индексацию в стеке. (Вы можете систематически победить эту решающую оптимизацию, например, имея exec ''
в начале каждого возможного звонящего - и, как следствие, увидите падение производительности вашей системы через пол).
За исключением присвоения местным именам вызывающего абонента, exec thecode in thelocals, theglobals
может делать примерно то, что вы хотите, и inspect
Модуль позволяет вам получить локальные и глобальные значения вызывающего абонента в полудумном виде (в той степени, в которой глубокая черная магия - которая заставила бы меня отправиться по почте на любого коллегу, предполагая, что он будет выполнен в производственном коде) - когда-либо может быть удостоена чести незаслуженная похвала, называя это "полуразумным", то есть;-).
Но вы указываете: "Я хочу иметь возможность выполнять любой код". и единственное решение этой однозначной спецификации (и спасибо за точность, так как она облегчает ответ!) - это затем использовать другой язык программирования.
Написана ли сторонняя библиотека на Python? Если да, вы можете переписать и перепривязать функцию "foo" во время выполнения с вашей собственной реализацией. Вот так:
import third_party
original_foo = third_party.foo
def my_foo(*args, **kwds):
# do your magic...
original_foo(*args, **kwds)
third_party.foo = my_foo
Я предполагаю, что исправление обезьян немного лучше, чем переписывание локальных кадров.;)