On Thu, 27 May 2021 at 15:49, Chris Angelico email@example.com wrote:
On Fri, May 28, 2021 at 12:25 AM Paul Moore firstname.lastname@example.org wrote:
On Thu, 27 May 2021 at 15:04, Chris Angelico email@example.com wrote:
def static(**statics): def deco(func): for name, value in statics.items(): setattr(func, name, value) func.__globals__["__me__"] = func return func return deco
@static(a=1) def f(): print(__me__.a)
Can't use globals like that, since there's only one globals() dict per module. It'd require some compiler magic to make __me__ work the way you want. But on the plus side, this doesn't require a run-time trampoline - all the work is done on the original function object.
Rats, you're right. Hacking globals felt like a code smell. I considered trying to get really abusive by injecting some sort of local but that's not going to work because the code's already compiled by the time the decorator runs:
... print(__me__.a) ...
2 0 LOAD_GLOBAL 0 (print) 2 LOAD_GLOBAL 1 (__me__) 4 LOAD_ATTR 2 (a) 6 CALL_FUNCTION 1 8 POP_TOP 10 LOAD_CONST 0 (None) 12 RETURN_VALUE
So yes, without compiler support you can only go so far (but you could always use the _getframe approach instead).
So, yeah, add it to the pile.
Yep. It's an interesting exercise, is all, and honestly, I don't think I'd use static much anyway, so something "good enough" that works now is probably more than enough for me personally.
I do think that having a compiler supported way of referring efficiently to the current function (without relying on looking it up by name) would be an interesting alternative proposal, if we *are* looking at actual language changes - it allows for something functionally equivalent to statics, without the performance advantage but in compensation it has additional uses (recursion, and more general access to function attributes). I'm not going to push for it though, as I say, I don't have enough use for it to want to invest the time in it.