static keyword

N

Nick Jacobson

I believe the following "static" command would be useful in Python.

def foo():
static i = [10, 11]
static firstcall = True
if firstcall:
print "First pass"
firstcall = False
i[0] += 1
print i[0]
foo()
foo()


This would output:

First pass
11
12

Just like in C, the variables i and firstcall are only assigned the
first time foo() is called. To get this effect currently, one could
use default arguments or wrapping the whole thing in a class. Both of
these solutions seem like hacks, the above method IMO is more
Pythonic. :)

I have a feeling this has been discussed before, but I can't find
anything on it. Thanks,

--Nick
 
P

Peter Hansen

Nick said:
I believe the following "static" command would be useful in Python. [snip]
Just like in C, the variables i and firstcall are only assigned the
first time foo() is called. To get this effect currently, one could
use default arguments or wrapping the whole thing in a class. Both of
these solutions seem like hacks, the above method IMO is more
Pythonic. :)

I'm not sure how to interpret the smiley, but I'll take it
you weren't actually joking...

Why do you call using OO ("wrapping it in a class", as you say)
a "hack"? Generally speaking, using objects to contain state
information such as this is exactly what most people would call
the cleanest, best approach.

class HasState:
def __init__(self):
self.firstCall = True
self.i = [10, 11]

def foo(self):
if self.firstCall:
print "First pass"
self.firstCall = False
self.i[0] += 1
print self.i[0]

obj = HasState()
obj.foo()
obj.foo()

Now, without arguing that it has 11 lines instead of 8 to do the
same thing (because then I'd just point out that this was a contrived
example anyway, and that it is more easily extended, and more obvious
what was going on, etc. :) ), can you describe why you call this is
a "hack"?

-Peter
 
Y

Yermat

I do not ! Static variable are like global...
[snip]
Just like in C, the variables i and firstcall are only assigned the
first time foo() is called. To get this effect currently, one could
use default arguments or wrapping the whole thing in a class. Both of
these solutions seem like hacks, the above method IMO is more
Pythonic. :)

or use global with carefully choosed name...

class HasState:
def __init__(self):
self.firstCall = True
self.i = [10, 11]

def foo(self):
if self.firstCall:
print "First pass"
self.firstCall = False
self.i[0] += 1
print self.i[0]

obj = HasState()
obj.foo()
obj.foo()

Like this solution because most of the timethis is not really static
variable that we want but a per context "static" variable.

Anyway, if this is really static variable that you want,
what about this : :cool:
>>> i = [10 ,11]
>>> firstcall = True
>>>
>>> def foo():
.... global i
.... global firstcall
.... if firstcall:
.... print "First pass"
.... firstcall = False
.... i[0] += 1
.... print i[0]
....First pass
1112
 
G

Georgy

| I believe the following "static" command would be useful in Python.
|
| def foo():
| static i = [10, 11]
| static firstcall = True
| if firstcall:
| print "First pass"
| firstcall = False
| i[0] += 1
| print i[0]
| foo()
| foo()
|
|
| This would output:
|
| First pass
| 11
| 12
|
| Just like in C, the variables i and firstcall are only assigned the
| first time foo() is called. To get this effect currently, one could
| use default arguments or wrapping the whole thing in a class. Both of
| these solutions seem like hacks, the above method IMO is more
| Pythonic. :)

"Pythonic" way is to use the oddity of default arguments:

def foo( static_vars = {'i':[10, 11],'firstcall':True} ):
if static_vars['firstcall']:
print "First pass"
static_vars['firstcall'] = False
static_vars['i'][0] += 1
print static_vars['i'][0]
foo()
foo()
 
D

Daniel Dittmar

Nick said:
I believe the following "static" command would be useful in Python. [...]
Just like in C, the variables i and firstcall are only assigned the
first time foo() is called. To get this effect currently, one could
use default arguments or wrapping the whole thing in a class. Both of
these solutions seem like hacks, the above method IMO is more
Pythonic. :)

You could also use funtion properties.... statictest.counter += 1
.... print statictest.counter
....2

But this uses two lookups: one for the function in module scope and one for
the property. Three if you want to do this in a method
(class.method.property).

Just to describe all the possibilities, I probably wouldn't use this myself.

Daniel
 
N

Nick Jacobson

Why do you call using OO ("wrapping it in a class", as you say)
a "hack"? Generally speaking, using objects to contain state
information such as this is exactly what most people would call
the cleanest, best approach.

class HasState:
def __init__(self):
self.firstCall = True
self.i = [10, 11]

def foo(self):
if self.firstCall:
print "First pass"
self.firstCall = False
self.i[0] += 1
print self.i[0]

obj = HasState()
obj.foo()
obj.foo()

Now, without arguing that it has 11 lines instead of 8 to do the
same thing (because then I'd just point out that this was a contrived
example anyway, and that it is more easily extended, and more obvious
what was going on, etc. :) ), can you describe why you call this is
a "hack"?

-Peter

I don't know if "hack" is the right word. What I meant is it seems
like overkill to have to make (and name) a class, plus add a second
function, every time you want a function to have a static variable.
 
N

Nick Jacobson

i = [10 ,11]
... global i
... global firstcall
... if firstcall:
... print "First pass"
... firstcall = False
... i[0] += 1
... print i[0]
...First pass
1112

Hmm. I would like it, but it pollutes the global namespace. Two
functions might want to use firstcall, for example (if they want to
just do something on the first pass). That's an error at most, and
renaming issues at the least.

Thanks for the idea, though..
 
J

Jack Diederich

Why do you call using OO ("wrapping it in a class", as you say)
a "hack"? Generally speaking, using objects to contain state
information such as this is exactly what most people would call
the cleanest, best approach.

class HasState:
def __init__(self):
self.firstCall = True
self.i = [10, 11]

def foo(self):
if self.firstCall:
print "First pass"
self.firstCall = False
self.i[0] += 1
print self.i[0]

obj = HasState()
obj.foo()
obj.foo()

Now, without arguing that it has 11 lines instead of 8 to do the
same thing (because then I'd just point out that this was a contrived
example anyway, and that it is more easily extended, and more obvious
what was going on, etc. :) ), can you describe why you call this is
a "hack"?

-Peter

I don't know if "hack" is the right word. What I meant is it seems
like overkill to have to make (and name) a class, plus add a second
function, every time you want a function to have a static variable.

Keeping state in functions is usually a "hack." Class instances have
state, functions just do stuff. That said you can get by just fine
using default arguments for small amounts of state in functions.

def foo(i=[]):
if (not i): # only true once
print "First!"
i.extend([10, 11])
i[0] += 1
print i[0]

But you really really don't want state in plain functions (as opposed
to member functions of objects). I would consider any function that
does something different when called twice with the same arguments broken.
Unless the name of the function starts with 'random' *wink*.

-jackdied
 
P

Peter Hansen

Nick said:
I don't know if "hack" is the right word. What I meant is it seems
like overkill to have to make (and name) a class, plus add a second
function, every time you want a function to have a static variable.

I can't recall the last time I wanted a function to have
a static variable. Years, it's been...

(That probably just says something about our approach to design
and coding. I'm not criticizing you, just explaining why what
I showed seems natural and simple to mean, but not to you.)

-Peter
 
M

Michael Walter

Peter said:
Nick said:
I believe the following "static" command would be useful in Python.
[snip]

Just like in C, the variables i and firstcall are only assigned the
first time foo() is called. To get this effect currently, one could
use default arguments or wrapping the whole thing in a class. Both of
these solutions seem like hacks, the above method IMO is more
Pythonic. :)


I'm not sure how to interpret the smiley, but I'll take it
you weren't actually joking...

Why do you call using OO ("wrapping it in a class", as you say)
a "hack"? Generally speaking, using objects to contain state
information such as this is exactly what most people would call
the cleanest, best approach.
> [...]
There's also a bunch of people who would consider this (modulo my
obvious mistakes ;) the cleanest, best approach:

(let ((first-call #t)
(i '(10 11)))
(define (foo)
(when (first-call)
(begin (display "first pass") (set! first-call #f))
(set! (array-ref i 0) (+ (array-ref i 0) 1))
(display (array-ref i 0))))

I.e. capture the state in a normal lexical variable.

Cheers,
Michael
 
S

Steve Simmons

Peter said:
I'm not sure how to interpret the smiley, but I'll take it
you weren't actually joking...
Why do you call using OO ("wrapping it in a class", as you say)
a "hack"? Generally speaking, using objects to contain state
information such as this is exactly what most people would call
the cleanest, best approach.

I'm not the original poster, but I'm going to side with him.

Class, to me, implies a fair number of things about the intended
use of what the author has written. Jacobson is talking about
a much simpler construct/feature than what one would normally
use a class for. His proposal might seem like mere syntactic
sugar to avoid making a class, but IMHO it will lead to code
that is more readable - code that doesn't imply it's anything
other than a function with a persistant, stateful variable.

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top