Множество неясных вопросов по этому вопросу решено с помощью OP. Смотрите ответы на изменения. Он сводится к (импорту) перехватывающих локальных объектов (переменных, определений, классов), так что они доступны для использования внутри определения.
См. Ответ ниже со встроенными комментариями, что и для чего.
# take 1, create local variable 'foo' with value 6. Not in function.
# >>> code is executed in local-scope <<<
varName = 'foo'
varValue = 42
localVarToEvaluate = varName + ' = varValue'
try:
exec(localVarToEvaluate) # (0) dict item becomes {varName : varValue}
print (localVarToEvaluate) # (1) prints > foo = varValue < dict item
except Exception as err:
print(str(err))
if 'foo' in locals():
print(locals()['foo']) # (2) prints > 42 < value
print(foo) # (3) prints > 42 < value
print("'foo' OK:", foo) # (4) prints > 'foo' OK: 42 < stringtext, value
# take 2, create local variable 'bar' with value 42
def func2(self):
# >>> code executed inside function and not local-scope <<<
varName = 'bar'
varValue = 42
localVar2Evaluate = varName + ' = varValue'
try:
exec(localVar2Evaluate) # (5) dict item becomes {varName : varValue}
print (localVar2Evaluate) # (6) prints > bar = varValue < dict item
except Exception as err:
print(str(err))
print ('local-scope :', '\n', locals()) # (7) {'bar': 42, 'localVar2Evaluate': 'bar = varValue', 'varValue': 42, 'varName': 'bar'}
if 'bar' in locals():
print(locals()['bar']) # (1)
print(bar) # (2) < --- python is not looking here in the locals() but inside the def for variable `bar` which is not made unless you give it access (hook or reference) via e.g. self.
print("'bar' OK:", bar) # (3)
# pass # uncomment any line above
x = 'a scotch... lets drink.. mystery solved!'
bar = "the local 'bar' variable is now available inside def func2().. It is: %s" % x
func2(bar)
Как видите, я (импорт) создаю ловушку для локальной переменной с varName 'bar', которая будет использоваться внутри определения с использованием self
. Это может быть любое имя t.b.h. См. Pydocs на self
и т. Д.
Результат:
bar = varValue
local-scope :
{'localVar2Evaluate': 'bar = varValue', 'varValue': 42, 'bar': 42, 'self': "the local 'bar' variable is now available inside def func2().. It is: a scotch... lets drink.. mystery solved!", 'varName': 'bar'}
42
the local 'bar' variable is now available inside def func2().. It is: a scotch... lets drink.. mystery solved!
'bar' OK: the local 'bar' variable is now available inside def func2().. It is: a scotch... lets drink.. mystery solved!
Если print('\n\n', locals())
ниже func (), вы получите следующий результат печати:
- 'bar': локальная переменная 'bar' теперь доступна внутри def
func2 () .. Это: скотч ... давай выпьем ... загадка разгадана! "
- 'localVarToEvaluate': 'foo = varValue'
- 'varValue': 42
- 'foo': 42
- 'varName': 'foo'
- 'x': 'скотч ... давай выпьем ... загадка разгадана!'
- 'func2': "<" function func2 at 0x000002B070027F28 ">" # без "outside"> ".
В пуле 7 вы видите связанный func2.
ОБНОВЛЕНИЕ 4:
Переключение между python 2.7.16 и 3.5.2 не выявило никаких изменений для dict localals () и ОДНОГО изменения в dict globals (), как показано ниже.
В 2.7: 'variables': set([('bar', 42), ('foo', 6)])
В 3.5: 'variables': {('bar', 42), ('foo', 6)}
... это set()
выглядит мне причиной, почему это больше не работает, что вы обратились в 3.5.
Я протестировал его, адаптировав ваш скрипт:
import sys
print (sys.version)
variables = {('foo', 6), ('bar', 42)}
def func():
for varData in variables:
varName, varValue = varData
localVarToEvaluate = varName + ' = varValue'
try:
exec(localVarToEvaluate)
print ('t2\n', locals())
except Exception as err:
print(str(err))
if varName not in globals():
print("Variable names '", varName, "can't be found in global scope!")
if 'foo' in globals():
print("'foo' OK:", foo) # exception here
else:
print("'foo' not available!")
if 'bar' in globals():
print("'bar' OK:", bar)
else:
print("'bar' not available!")
print ('t1\n', globals())
func()
Тогда ... это все еще может быть exec. Поэтому я отключил запуск func()
, а разница в globals()
осталась. Так что я думаю, что разница в globals()
функция, а не exec
.