Anonymus functions revisited
Kay Schluehr
kay.schluehr at gmx.net
Wed Mar 23 06:43:31 EST 2005
Duncan Booth wrote:
> Do I really need to mention that the whole concept here is broken.
This
> only works if you call it from global scope. If you call it from
inside a
> function it [usually] won't work:
>
> >>> def makeVars(**nameVals):
> sys._getframe(1).f_locals.update(nameVals)
>
>
> >>> def test():
> try: b
> except NameError: print "Before makeVars: NameError"
> else: print "Before makeVars: Not NameError"
> makeVars(b=2)
> try: b
> except NameError: print "After makeVars: NameError"
> else: print "After makeVars: Not NameError"
>
>
> >>> import sys
> >>> test()
> Before makeVars: NameError
> After makeVars: NameError
> >>>
Yes.
To put it short:
def makeVars(**nameVals):
print "prev",sys._getframe(1).f_locals["z"]
sys._getframe(1).f_locals.update(nameVals)
print "post",sys._getframe(1).f_locals["z"]
def test():
z = 0
makeVars(z=2)
>>> z = 0
>>> makeVars(z=3)
prev 0
post 3
>>> test()
prev 0
post 0
The Python runtime uses the opcodes STORE_FAST and LOAD_FAST to
store/access local variables of a function.
Take a closer look at the code:
case STORE_FAST:
v = POP();
SETLOCAL(oparg, v);
goto fast_next_opcode;
with
register PyObject **fastlocals
and macros
#define GETLOCAL(i) (fastlocals[i])
#define SETLOCAL(i, value) do { PyObject *tmp = GETLOCAL(i); \
GETLOCAL(i) = value; \
Py_XDECREF(tmp); } while (0)
The local variables will be stored in the pointer array fastlocals not
within a Python dict.
If a variable is created as a global it will be stored using the
STORE_NAME opcode instead:
case STORE_NAME:
w = GETITEM(names, oparg);
v = POP();
if ((x = f->f_locals) != NULL) {
if (PyDict_CheckExact(x))
err = PyDict_SetItem(x, w, v);
else
err = PyObject_SetItem(x, w, v);
Py_DECREF(v);
if (err == 0) continue;
break;
}
which clearly accesses a Python dict for storage.
Regards Kay
More information about the Python-list
mailing list