On 27 May 2021, at 18:15, Steven D'Aprano email@example.com wrote:
On Thu, May 27, 2021 at 04:53:17PM +0200, Ronald Oussoren via Python-ideas wrote:
Statics are still hidden global state
How are they *global* state when they are specific to an individual function?
We can already get the basic behaviour of statics right now, only with an ugly hack that pollutes the function parameter list and is inconvenient to use.
static = 
def spam(arg, static=): static += arg return static
def eggs(arg, static=): static -= arg return static
Is it your argument that all three `static` variables are using shared global state? If not, then I have no idea what you mean by insisting that statics are "hidden global state". They are hidden state, but not global. Just like closures and instance attributes.
I honestly don’t see the difference between:
def spam(arg, static=): …
_static = 0 def spam(arg): global _static; …
The difference is where the state is stored. State in the latter example is less tightly coupled to the function and is easier to access externally, but for both cases there is a documented way to access them (spam.__defaults__[’static’] for the first example). In both cases there’s effectively a singleton object that stores data, which makes testing harder because it is harder to ensure the right preconditions for testing (e.g. some other code might have called the function and affected the function state in an unexpected way).
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.
It sounds like your problem is with *mutable state* in general. Global variables, instance attributes, class attributes, they all have exactly the same issues.
So don't use mutable state. Nobody is forcing you to use this feature if you prefer to write in a functional style with no mutable state.
I don’t think anyone has accused me of advocating functional programming before ;-)
I don’t have a problem with mutable state in general, just with singletons. That includes globals and class attributes, but not necessarily instance variables or other data structures.
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()
Congratulations, you've just used static local variables. You just used closures for the implementation.
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).
You: "Global state is bad! Don't use global state!"
Also you: "Don't use local state (closures)! Use global state, it's better!"
No, I wrote that *if* you want to use global state there are already multiple ways to do this.
I’m just as flawed as anyone and do use global state when that’s convenient. But this has a tendency of causing problems later on, especially in larger projects.
Slightly more seriously, I also wrote that the OP hasn’t provided a better reason for adding this feature than “other languages have this”.
Twitter / micro.blog: @ronaldoussoren Blog: https://blog.ronaldoussoren.net/