¿Cuál es el equivalente en Python de las variables estáticas dentro de una función?
¿Cuál es el equivalente idiomático en Python de este código C/C++?
void foo()
{
static int counter = 0;
counter++;
printf("counter is %d\n", counter);
}
específicamente, ¿cómo se implementa el miembro estático en el nivel de función, a diferencia del nivel de clase? ¿Y colocar la función en una clase cambia algo?
Un poco al revés, pero esto debería funcionar:
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
foo.counter = 0
Si desea que el código de inicialización del contador esté en la parte superior en lugar de en la parte inferior, puede crear un decorador:
def static_vars(**kwargs):
def decorate(func):
for k in kwargs:
setattr(func, k, kwargs[k])
return func
return decorate
Luego usa el código como este:
@static_vars(counter=0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
Desafortunadamente , aún será necesario que uses el foo.
prefijo.
(Crédito: @ony )
Puede agregar atributos a una función y usarla como una variable estática.
def myfunc():
myfunc.counter += 1
print myfunc.counter
# attribute must be initialized
myfunc.counter = 0
Alternativamente, si no desea configurar la variable fuera de la función, puede usar hasattr()
para evitar una AttributeError
excepción:
def myfunc():
if not hasattr(myfunc, "counter"):
myfunc.counter = 0 # it doesn't exist yet, so initialize it
myfunc.counter += 1
De todos modos, las variables estáticas son bastante raras y deberías encontrar un lugar mejor para esta variable, probablemente dentro de una clase.
También se podría considerar:
def foo():
try:
foo.counter += 1
except AttributeError:
foo.counter = 1
Razonamiento:
- mucho pitónico ("pedir perdón, no permiso")
- use una excepción (lanzada solo una vez) en lugar de
if
una rama (piense en la excepción StopIteration )
Mucha gente ya ha sugerido probar 'hasattr', pero hay una respuesta más sencilla:
def func():
func.counter = getattr(func, 'counter', 0) + 1
Sin intentar/excepto, sin probar hasattr, solo getattr con un valor predeterminado.