Von CPython Quelle, Objects/frameobject.c
:
static PyMemberDef frame_memberlist[] = {
{"f_back", T_OBJECT, OFF(f_back), RO},
{"f_code", T_OBJECT, OFF(f_code), RO},
{"f_builtins", T_OBJECT, OFF(f_builtins),RO},
{"f_globals", T_OBJECT, OFF(f_globals), RO},
{"f_lasti", T_INT, OFF(f_lasti), RO},
{"f_exc_type", T_OBJECT, OFF(f_exc_type)},
{"f_exc_value", T_OBJECT, OFF(f_exc_value)},
{"f_exc_traceback", T_OBJECT, OFF(f_exc_traceback)},
{NULL} /* Sentinel */
};
...
static PyGetSetDef frame_getsetlist[] = {
{"f_locals", (getter)frame_getlocals, NULL, NULL},
{"f_lineno", (getter)frame_getlineno,
(setter)frame_setlineno, NULL},
{"f_trace", (getter)frame_gettrace, (setter)frame_settrace, NULL},
{"f_restricted",(getter)frame_getrestricted,NULL, NULL},
{0}
};
Für die PyMemberDef
, die Fahnen RO
oder READONLY
bedeutet, es ist Attribute schreibgeschützt sind. Für die PyGetSetDef
, wenn es nur einen Getter hat, ist es nur lesbar. Dies bedeutet, dass alle Attribute außer f_exc_type
, f_exc_value
, f_exc_traceback
und f_trace
nach der Erstellung schreibgeschützt sind. Dies wird auch in der Dokumentation unter Data model erwähnt.
Die Objekte, auf die sich die Attribute beziehen, sind nicht unbedingt schreibgeschützt. Sie können dies tun:
>>> f = sys._getframe()
>>> f.f_locals['foo'] = 3
>>> foo
3
>>>
Obwohl dies in dem Dolmetscher arbeitet, schlägt es innerhalb von Funktionen. Die Ausführungs-Engine verwendet ein separates Array für lokale Variablen (f_fastlocals
), das beim Zugriff auf f_locals
zusammengeführt wird, aber die Umkehrung ist nicht wahr.
>>> def foo():
... x = 3
... f = sys._getframe()
... print f.f_locals['x']
... x = 4
... print f.f_locals['x']
... d = f.f_locals
... x = 5
... print d['x']
... f.f_locals
... print d['x']
...
>>> foo()
3
4
4
5
>>>
Auf dem globalen Rahmen bezieht sich f_local
auf f_globals
, die diesen Trick Arbeit im Interpreter macht. Die Änderung f_globals
funktioniert, betrifft jedoch das gesamte Modul.
Interessant. Dies scheint das Verhalten einer interaktiven Shell zu sein, aber f_locals scheint nur in einem Skript gelesen zu werden. Siehe meine erweiterte Frage - dieser Codeausschnitt, der in einem Interpreter ausgeführt wird, scheint schreibgeschützt zu sein. – ConcernedOfTunbridgeWells