For a little background, I'm working on making an edit and continue support in python a little more robust. So, in replacing references to unmodifiable types like tuples and bound-methods (instance or class), I iterate over gc.get_referrers.
So, I'm working on frame types, and wrote this code::
def replaceFrame(self, ref, oldValue, newValue): for name, value in ref.f_locals.items(): if value is oldValue: ref.f_locals[name] = newValue assert ref.f_locals[name] is newValue
But unfortunately, the assert fires. f_locals is writable, but not modifiable. I did a bit of searching on Google Groups, and found references to a desire for smalltalk like "swap" functionality using a similar approach, but no further ideas or solutions.
While I am full well expecting the smack of "don't do that", this functionality would be very useful for debugging long-running applications. Is this possible to implement in CPython and ports? Is there an optimization reason to not do this?
So it would be doable, but it is not brain-dead simple if you want to keep the interface of a dict. Locals, in the frame, are an array of PyObjects (see PyFrameObject->f_localsplus). When you request f_locals that returns a dict that was created by a function that takes the array, traverses it, and creates a dict with the proper names (using PyFrameObject->f_code->co_varnames for the array offset -> name mapping). The resulting dict gets stored in PyFrameObject->f_locals. So it is writable as you discovered since it is just a dict, but it is not used in Python/ceval.c except for IMPORT_STAR; changes are just never even considered. The details for all of this can be found in Objects/frameobject.c:PyFrame_FastToLocals() .
The interesting thing is that there is a corresponding PyFrame_LocalsToFast() function that seems to do what you want; it takes the dict in PyFrameObject->f_locals and propogates the changes into PyFrameObject->f_localsplus (or at least seems to; don't have time to stare at the code long enough to make sure it does that exactly). So the functionality is there (and is in the API even). It just isn't called explicitly except in two points in Python/ceval.c where you can't get at it. =)
As to making changes to f_locals actually matter would require either coming up with a proxy object that is stored in f_locals instead of a dict and dynamically grab everything from f_localsplus as needed. That would suck for performance and be a pain to keep the dict API. So you can count that out.
Other option would be to add a function that either directly modified single values in f_localsplus, a function that takes a dict and propogates the values, or a function that just calls PyFrame_LocalsToFast() .
Personally I am against this, but that is because you would single-handedly ruin my master's thesis and invalidate any possible type inferencing one can do in Python without some semantic change. But then again my thesis shows that amount of type inferencing is not worth the code complexity so it isn't totally devastating. =)
And you are right, "don't do that". =)
Back to the putrid, boggy marsh of JavaLand for me...
-Brett _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com