You can just use nonlocal variables:
def stator():
static_var_1 = 0
def myfunc(n):
nonlocal static_var_1
static_var_1 += n
return static_var_1
return myfunc
myfunc = stator()
del stator
Or you can attach any variable to the function itself:
def myfunc(n):
if not hasattr(myfunc, "static_var_1"):
myfunc.static_var_1 = 0
myfunc.static_var_1 += n
return myfunc.static_var_1
There are several options to get the effect that static variables would
have,
not to mention that states of this type are better held as class attributes
anyway.
BTW:
# callable singleton - AKA "function":
class myfunc(metaclass=lambda *args: type(*args)()):
def __init__(self):
self.static_var_1 = 0
def __call__(self, n):
self.static_var_1 += n
return self.static_var_1
Or, as you put it in the first e-mail, the static var could be built into a
data structure in
the default arguments of the function.
(There are also contextvars, threading.local, etc...)
I can't see a separate "static" declaration being of any use.
Beginners needing the functionality should just resort to either globals or
plain classes to keep state. As you get the way Python works,
there are plenty of ways to keep the state, without making
the language more complicated.
On Thu, 27 May 2021 at 14:06, Chris Angelico
On Fri, May 28, 2021 at 2:44 AM Shreyan Avigyan
wrote: My proposal is somewhat the sum of all of your ideas. Well I propose
there should a STORE_STATIC_FAST opcode that stores a static variable. Static variable will be declared only once and will be initialized to None (statement syntax will be similar to that of global). It will be initialized in MAKE_FUNCTION. Now it will be set by STORE_STATIC_FAST. Where will the variables be stored? It will have references in locals and __statics__. Therefore LOAD_FAST can find it. So I don't hope there will be performance decrease but performance increase is also not guaranteed. :-)
The duplicated store fixes half the problem, but it still fails on the recursion example that I posted in reply to Steve. It would be a nice optimization, but it may or may not be sufficient.
And if these are thread unsafe then is __defaults__ also thread unsafe?
Thread safety isn't a problem with constants. Python guarantees that internal details (like CPython's reference counts) aren't going to be trampled on, and inside your code, nothing is going to change __defaults__ (unless you're doing something bizarre, in which case it isn't about __defaults__ any more). Thread safety only becomes an issue when you have something like this:
counter = 0 def get_next(): global counter counter += 1 return counter
This disassembles to:
6 0 LOAD_GLOBAL 0 (counter) 2 LOAD_CONST 1 (1) 4 INPLACE_ADD 6 STORE_GLOBAL 0 (counter)
7 8 LOAD_GLOBAL 0 (counter) 10 RETURN_VALUE
A context switch can happen between any two of those instructions. That means one thread could load the global, then another thread could load the same value, resulting in both of them writing back the same incremented value. Or, between opcodes 6 and 8 (between the lines of Python code), you could store the value, then fetch back a different value.
None of this is a problem if you're using constants. The only reason to use statics instead of global constants is performance - the "len=len" trick is specific to this performance advantage - but you don't have to worry about thread safety.
ChrisA _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/DD62RX... Code of Conduct: http://python.org/psf/codeofconduct/