On 27 May 2021, at 11:42, Chris Angelico <rosuav@gmail.com> wrote:

On Thu, May 27, 2021 at 7:20 PM Ronald Oussoren via Python-ideas
<python-ideas@python.org> wrote:
On 27 May 2021, at 09:56, Shreyan Avigyan <pythonshreyan09@gmail.com> wrote:

Static should behave much like Python's for loop variables.

I have no idea what this means.

For this particular question/proposal:  “static” variables in functions in C like languages are basically hidden global variables, and global variables are generally a bad idea.


Hmm, I'd distinguish a couple of things here. Global constants are
most certainly not a problem, and objects that last the entire run of
the program are not a problem either. The usual problem with "global
variables" is that they become hidden state, action-at-a-distance. You
can change the global in one function and it notably affects some
other function. Part of the point of statics is that they are *not*
global; they might live for the entire run of the program, but they
can't be changed by any other function, so there's no AaaD that will
mess with your expectations.

Statics are still hidden global state, and those can be problematic regardless of being function local or module global. Having global state like this affects testability and can affect threading as well.  

In Python you can get the same result with a global variable and the use of the “global” keyword in a function (or cooperating set of functions) when you want to update the global variable from that function.


That's globals, with all the risks thereof.

Closures or instances of classes with an ``__call__`` method can be used as well and can hide state (with the “consulting adults” caveat, the state is hidden, not inaccessible).


This would be the easiest way to manage it. But both of them provide a
way to have multiple independent, yet equivalent, states. If that's
what you want, great! But it can also be an unnecessary level of
confusion ("why would I ever make a second one of these? Why is there
a factory function for something that I'll only ever need one of?"),
where static variables wouldn't do that.

The factory function doesn’t need to be part of the public API of a module, I’ve used a pattern like this to create APIs with some hidden state:

```
def make_api():
    state = ...

    def api1(…): …
    def ap2(…): …

    return api1, api2
api1, api2 = make_api()
```

I’m not saying that this is a particularly good way to structure code, in general just using a private module global is better (assuming the design calls for some kind of global state). 


There is one namespace that would very aptly handle this kind of
thing: the function object itself.

def count():
...     count.cur += 1
...     return count.cur
...
count.cur = 0
count()
1
count()
2
count()
3
count()
4

As long as you can reference your own function reliably, this will
work. There may be room for a keyword like this_function, but for the
most part, it's not necessary, and you can happily work with the
function by its name. It's a little clunkier than being able to say
"static cur = 0;" to initialize it (the initializer has to go *after*
the function, which feels backwards), but the functionality is all
there.

I generally dislike functions with internal state like this.

Ronald



Twitter / micro.blog: @ronaldoussoren
Blog: https://blog.ronaldoussoren.net/