Это была цитата из документации…
Т.е. оно работает в интерпретаторе, а в коде:
def f():
a = 'zzz'
locals()[a] = 'xxx'
print(a)
f()
exec активно используют в базаре, и довольны…
def f():
a = 'zzz'
locals()[a] = 'xxx'
print(a)
f()
def locals():
import sys
frame = sys._getframe()
return frame.f_locals
>>> def f():
... a = 'zzz'
... locals()[a] = 'xxx'
... print a
...
>>> f.func_code.co_varnames
('a',)
>>> import dis
>>> dis.dis(f)
2 0 LOAD_CONST 1 ('zzz')
3 STORE_FAST 0 (a)
...
4 19 LOAD_FAST 0 (a)
22 PRINT_ITEM
case LOAD_FAST:
x = GETLOCAL(oparg);
if (x != NULL) {
Py_INCREF(x);
PUSH(x);
goto fast_next_opcode;
}
format_exc_check_arg(PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(co->co_varnames, oparg));
break;
#define GETLOCAL(i)<--->(fastlocals[i])
fastlocals = f->f_localsplus;
typedef struct _frame {
...
PyObject *f_localsplus[1];<>/* locals+stack, dynamically sized */
} PyFrameObject;
case STORE_FAST:
v = POP();
SETLOCAL(oparg, v);
goto fast_next_opcode;
#define SETLOCAL(i, value) do { PyObject *tmp = GETLOCAL(i); \
GETLOCAL(i) = value; \
Py_XDECREF(tmp); } while (0)
ZZZДеколи такі речі необхідні. знаю 3 таких приклади - py_zipimport.py (сам гвідо його написав;) ) І для відкладених імпортів - zope.deferredimport i підозрюю що і bzr.lazy_import так працює. Також приклад є в старих версіях PloneTestCase (хоча там думаю можна було обійтись без того)
ИМХО, “динамические переменнве”, это хороший пример плохого кода.
ZZZсогласен!
ИМХО, “динамические переменнве”, это хороший пример плохого кода.