Static variables [was Re: syntax difference]

Bart bart at 1
Sat Jun 23 14:41:58 EDT 2018


  To: Steven D'Aprano
From: "Bart" <bart at 1:261/38.remove-r7u-this>

  To: Steven D'Aprano
From: Bart <bc at freeuk.com>

On 23/06/2018 04:51, Steven D'Aprano 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!

This is an example of a simple concept getting so out of hand that it will
either never be implemented, or the resulting implementation becomes
impractical to use.

This is what we're trying to do:

     def nextx():
         static x = 0
         x += 1
         return x

And this is the simplest equivalent code in current Python that will cater for
99% of uses:

     _nextx_x = 0

     def nextx():
         global _nextx_x
         _nextx_x += 1
         return _nextx_x

No nested functions. No generating new instances of functions complete with a
new set of statics each time you happen to refer to the name. (Which sounds to
me as useful as creating a new instance of an import when you copy its name,
complete with a separate set of its globals. Isn't this stuff what classes are
for?)

(At what point would that happen anyway; if you do this:

     g = nextx              # hypothetical version would static

it will create a new instance of 'nextx'. But it won't create one here, just
before () is applied:

     nextx()         # ?

Or how about here:

     listoffunctions = (nextx1, nextx2, nextx3)

     listoffunctions[i]()     # ?

)

--
bartc

-+- BBBS/Li6 v4.10 Toy-3
 + Origin: Prism bbs (1:261/38)

--- BBBS/Li6 v4.10 Toy-3
 * Origin: Prism bbs (1:261/38)



More information about the Python-list mailing list