From: "Chris Angelico" <chris.angelico@1:261/38.remove-r7u-this>
From: Chris Angelico <ros...@gmail.com> On Sat, Jun 23, 2018 at 1:51 PM, Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote: > On Wed, 20 Jun 2018 14:18:19 +1000, Chris Angelico wrote: > >> Ah. Yeah, that would be a plausible feature to add to Python. But in C, >> a static variable is basically the same thing as a global variable, >> except that its name is scoped to the function. There is only one of it. >> What happens in Python? For instance: >> >> def f(): >> def g(): >> static x = 0 >> x += 1 >> return x >> return g >> >> Does the static variable exist once for each instance of g()? If so, >> it'll behave like a closure variable; if not, it'll behave like a >> global. Either way, I'm pretty much certain that people will expect the >> other. > > Yes, but given the normal execution model of Python, only one solution is > valid. Since the function g is created fresh each time f is called, each > one gets a fresh static x. > > If you want all the g's to share the same x, you would write: > > def f(): > static x = 0 > def g(): > x += 1 > return x > return g > > > In this case, every invocation of f shares the same static x, and all the > g's refer to that same x, using the ordinary closure mechanism. In the > earlier case, each invocation of f creates a brand new g with its own x. > > Simple and elegant. > > This could at last get rid of that useful but ugly idiom: > > def function(real, arguments, len=len, int=int, str=str): > ... > > if we allowed the "static" declaration to access the values from the > surrounding scope: > > def function(real, arguments): > static len=len, int=int, str=str > > But I think nicer than that would be a decorator: > > @static(len=len, int=int, str=str) > def function(real, arguments): > ... > > which adds local variables len, int, str to the function, with the given > values, and transforms all the bytecode LOAD_NAME len to LOAD_FAST len > (or whatever). > > (We might need a new bytecode to SET_STATIC.) > > That would be a nice bytecode hack to prove the usefulness of the concept! > Okay, that makes sense. So in a way, static variables would be like closure variables with an invisible outer function. These would be roughly equivalent: def f(): static x = 0 x += 1 return x def make_f(): x = 0 def f(): nonlocal x x += 1 return x return f f = make_f() I don't think LOAD_FAST is appropriate (those cells get disposed of when the function returns), but transforming those lookups into closure lookups would be a reasonable way to do it I think. For getting rid of the "len=len" trick, though, I would REALLY like to transform those into LOAD_CONST. That'd be a fun bytecode hack all on its own. In fact, I'm gonna have a shot at that. An "early bind these names" decorator. ChrisA -+- BBBS/Li6 v4.10 Toy-3 + Origin: Prism bbs (1:261/38) --- BBBS/Li6 v4.10 Toy-3 * Origin: Prism bbs (1:261/38) -- https://mail.python.org/mailman/listinfo/python-list