[Python-ideas] 'Injecting' objects as function-local constants
jh at improva.dk
Sat Jun 18 13:04:45 CEST 2011
On 2011-06-18 06:03, Steven D'Aprano wrote:
> Nick Coghlan wrote:
>> On Fri, Jun 17, 2011 at 10:12 PM, Steven D'Aprano
>> <steve at pearwood.info> wrote:
>>> You have missed a fourth option, which I have been championing: make
>>> an ordinary function, available from the functools module. The
>>> *implementation* of inject almost certainly will require support from
>>> compiler, but that doesn't mean the interface should!
>> No, I didn't miss it, I left it out on purpose because I think messing
>> with the runtime name lookup semantics is a terrible idea.
I think that depends on what you count as part of the runtime name
> Isn't changing name lookup semantics at runtime precisely what JIT
> compilers do? But it doesn't really matter, because that's not what I'm
> proposing. I'm not suggesting that the lookup semantics should be
> changed when the function is called. I'm saying that a new function
> should be created, based on the original function, with the desired
> In principle, this could be as simple as:
> - make a copy of the function object
> - in the copy, add cells for any injected variable
> - and modify the copied code object to change the appropriate
> LOAD_GLOBAL opcodes to LOAD_DEREF (and similarly for rebindings).
> although I dare say that in practice there'll be a certain amount of
> book-keeping required to make it work reliably.
If you want the injected values to also affect functions that are
defined within the decorated function it gets a lot more complicated.
But yes, in theory it could work.
One thing that would make it a *lot* easier to write such an "inject"
function would be if we could replace the way globals are looked up to
use cells as well. I am thinking of a different "kind" of cell that
wouldn't hold its value itself but get it from the module globals the
way LOAD_GLOBAL does today. This cell would be in the __closures__ of
the function and could be replaced using a decorator like Steven proposed.
A consequence of this would be that you could optionally allow
"nonlocal" to bind global names when there are no suitable nonlocal
names to bind to (e.g. in a top-level function). It has always slightly
bothered me that you couldn't do that, because it makes it harder to
move code between levels.
As written, this would probably slow down access to globals a little
bit. However I have another idea (basically a more backward-compatible
variation of PEP 280) that would let us use cells or cell-like objects
for almost all accesses, at the cost of changing <module>.__dict__ to be
a dict *subclass*.
More information about the Python-ideas