
On Thu, May 27, 2021 at 08:46:03AM -0400, Ricky Teachey wrote:
Couldn't you already get pretty close to this by attaching your static values to the function __dict__?
Sure, we can use function attributes as a form of static storage, and I have done that. It is sometimes quite handy. But it's not really the same as proper static variables.
(1) It will be much less convenient. We have to write `func.variable` when we want `variable`, and if the function gets rebound to a new name, the call will fail.
(2) The performance will be worse. The name look-up to get `func` is a relatively slow LOAD_GLOBAL instead of LOAD_FAST, and then on top of that we need to do a second name look-up, using attribute access.
And if the func happens to be a method rather than a top level function, then we end up with three lookups: `self.method.variable`. And that could involve a deep inheritence chain.
(3) And the semantics are completely different:
- Function attributes are intended to be visible to the caller; they should be part of the function's API, just like any other attribute.
- Static variables are intended to be internal to the function, they are not part of the function's API. They are conceptually private to the function.
(At least as "private" as Python allows, given it's dynamic nature.)
[...]
But could there be a decorator that links the function __dict__ to locals(), so they are intertwined?
I doubt that this would be possible, without large changes to the internal workings of functions.
The locals dict in the function body would look something like this:
ChainMap(locals(), {'a':1})
Are you aware that the locals() dictionary inside functions is a snapshot of the actual, true, hidden locals? Outside of a function, locals() returns the true global dict which is used to hold variables, so this works fine:
x = 1 locals()['x'] = 99 # locals() here returns globals() print(x) # 99
But inside a function, well, try it for yourself :-)
def test(): x = 1 locals()['x'] = 99 print(x)
I'm not an expert on the internals of functions, but I think that my earlier proposal could be added to the existing implementation, while your linking values proposal would require a full re-implementation of how functions operate.