In Perl 5.10, I can say:
sub foo () {
state $x = 1;
say $x++;
}
foo();
foo();
foo();
...and it will print out:
1
2
3
Does Python have something like this?
In Perl 5.10, I can say:
sub foo () {
state $x = 1;
say $x++;
}
foo();
foo();
foo();
...and it will print out:
1
2
3
Does Python have something like this?
Yes, though you have to declare your global variable first before it is encountered in foo
:
x = 0
def foo():
global x
x += 1
print x
foo()
foo()
foo()
EDIT: In response to the comment, it's true that python has no static variables scoped within a function. Note that x
in this example is only exposed as global to the rest of the module. For example, say the code above is in test.py
. Now suppose you write the following module:
from test import foo
x = 100
foo()
foo()
The output will be only 1
and 2
, not 101
and 102
.
A class may be a better fit here (and is usually a better fit for anything involving "state"):
class Stateful(object):
def __init__(self):
self.state_var = 0
def __call__(self):
self.state_var = self.state_var + 1
print self.state_var
foo = Stateful()
foo()
foo()
Python has generators which do something similar:
http://stackoverflow.com/questions/231767/can-somebody-explain-me-the-python-yield-statement
You could also use something like
def static_num2():
k = 0
while True:
k += 1
yield k
static = static_num2().next
for i in range(0,10) :
print static()
to avoid a global var. Lifted from this link about the same question.
The closest parallel is probably to attach values to the function itself.
def foo():
foo.bar = foo.bar + 1
foo.bar = 0
foo()
foo()
foo()
print foo.bar # prints 3
Not sure if this is what you're looking for, but python has generator functions that don't return a value per se, but a generator object that generates a new value everytime
def gen():
x = 10
while True:
yield x
x += 1
usage:
>>> a = gen()
>>> a.next()
10
>>> a.next()
11
>>> a.next()
12
>>> a.next()
13
>>>
look here for more explanation on yield:
http://stackoverflow.com/questions/231767/can-somebody-explain-me-the-python-yield-statement
>>> def foo():
x = 1
while True:
yield x
x += 1
>>> z = iter(foo())
>>> next(z)
1
>>> next(z)
2
>>> next(z)
3
Not that I'm recommending this, but just for fun:
def foo(var=[1]):
print var[0]
var[0] += 1
This works because of the way mutable default arguments work in Python.
Here's one way to implement a closure in python:
def outer():
a = [4]
def inner():
print a[0]
a[0] = a[0] + 1
return inner
fn = outer()
fn() # => 4
fn() # => 5
fn() # => 6
I borrowed this example verbatim from a python mailing list post.
The preferable way is to use class or generator (yield
).
For the sake of completeness here's a variant w/ closure in Python 3.x:
>>> def make_foo():
... x = 1
... def foo():
... nonlocal x
... print(x)
... x += 1
... return foo
...
>>> foo = make_foo()
>>> foo()
1
>>> foo()
2
>>> foo()
3
Here's another dirty cheap way to do it, it's a variation on Tryiptich's answer, but using decorators
def static_var( name, value ):
def dec( function ):
setattr( function, name, value )
return function
return dec
@static_var( 'counter', 0 )
def counting_function():
counting_function.counter = counting_function.counter + 1
print counting_function.counter
"""
>>> counting_function()
1
>>> counting_function()
2
>>> counting_function()
3
>>> counting_function()
4
>>> counting_function()
5
>>>
"""