Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Static Variables in Python?

3,828 views
Skip to first unread message

Michael Yanowitz

unread,
Jul 31, 2006, 3:21:23 PM7/31/06
to pytho...@python.org
Is it possible to have a static variable in Python -
a local variable in a function that retains its value.

For example, suppose I have:

def set_bit (bit_index, bit_value):
static bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
bits [bit_index] = bit_value

print "\tBit Array:"
int i
while (i < len(bits):
print bits[i],
print '\n'


I realize this can be implemented by making bits global, but can
this be done by making it private only internal to set_bit()? I don't
want bits to be reinitialized each time. It must retain the set values
for the next time it is called.


Thanks in advance:
Michael Yanowitz

Roel Schroeven

unread,
Jul 31, 2006, 3:49:48 PM7/31/06
to
Michael Yanowitz schreef:

You could do it by defining static_bits as a keyword parameter with a
default value:

>>> def set_bit(bit_index, bit_value, static_bits=[0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0]):
static_bits[bit_index] = bit_value
return static_bits

>>> set_bit(2, 1)
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> set_bit(3, 1)
[0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> set_bit(2, 0)
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

It might be a better idea to use a class for this though:

>>> class Bits(object):
def __init__(self):
self.bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
def set(self, index, value):
self.bits[index] = value
return self.bits


>>> bits = Bits()
>>> bits.set(2, 1)
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> bits.set(3, 1)
[0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> bits.set(2, 0)
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

When using a class, you can have different lists of bits independently
of each other in a program. And you can define other operations on the
bits: you could for example create methods to set or clear all bits at
once. With your approach, set_bit is the only function that has access
to the bits so you can't easily create other operations.

--
If I have been able to see further, it was only because I stood
on the shoulders of giants. -- Isaac Newton

Roel Schroeven

tac-tics

unread,
Jul 31, 2006, 3:50:54 PM7/31/06
to

If you declare bits in set_bit() as "global bits = ...", it will create
it as a global variable without you having to declare it outside of the
function. Just be careful about name conflicts.

bearoph...@lycos.com

unread,
Jul 31, 2006, 3:57:55 PM7/31/06
to
tac-tics:

> If you declare bits in set_bit() as "global bits = ...", it will create
> it as a global variable without you having to declare it outside of the
> function. Just be careful about name conflicts.

Are you sure?

def fun():
global x = 10
fun()
print x

Bye,
bearophile

John Salerno

unread,
Jul 31, 2006, 4:05:38 PM7/31/06
to

This works for me:

>>> def fun():
global x
x = 10


>>> fun()
>>> print x
10
>>>

But of course:

>>> def fun():
global x = 10

SyntaxError: invalid syntax
>>>

Carsten Haese

unread,
Jul 31, 2006, 3:52:25 PM7/31/06
to pytho...@python.org
On Mon, 2006-07-31 at 15:21, Michael Yanowitz wrote:
> Is it possible to have a static variable in Python -
> a local variable in a function that retains its value.
>
> For example, suppose I have:
>
> def set_bit (bit_index, bit_value):
> static bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
> bits [bit_index] = bit_value
>
> print "\tBit Array:"
> int i
> while (i < len(bits):
> print bits[i],
> print '\n'
>
>
> I realize this can be implemented by making bits global, but can
> this be done by making it private only internal to set_bit()? I don't
> want bits to be reinitialized each time. It must retain the set values
> for the next time it is called.

Python does not have static variables in the sense that C does. You can
fake it in various ways, though. If I had to do it, I'd define a
callable object instead of a function, along the lines of this:

class BitSetter(object):
def __init__(self):
self.bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
def __call__(self, bit_index, bit_value):
self.bits[bit_index] = bit_value
# do something with self.bits here...
print self.bits

set_bit = BitSetter()

Now you can call set_bit(...) as if it were a function, and it'll behave
the way you want.

Hope this helps,

Carsten.


Bruno Desthuilliers

unread,
Jul 31, 2006, 4:30:06 PM7/31/06
to
Roel Schroeven a écrit :

> Michael Yanowitz schreef:
>
>> Is it possible to have a static variable in Python - a local
>> variable in a function that retains its value.
>>
(snip)

>
> You could do it by defining static_bits as a keyword parameter with a
> default value:
>
(snip)

> It might be a better idea to use a class for this though:
>
(snip)

Last solution being to use a closure:

def make_bits():


bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

def set_bit(bit_index, bit_value):
bits[bit_index] = bit_values
def get_bits():
# returns a copy so we don't overwrite
return bits[:]
return set_bit, get_bits

set_bit, get_bits = make_bits()

But the better solution is probably to make it a class.

Cliff Wells

unread,
Jul 31, 2006, 4:02:17 PM7/31/06
to Michael Yanowitz, pytho...@python.org
On Mon, 2006-07-31 at 15:21 -0400, Michael Yanowitz wrote:
> Is it possible to have a static variable in Python -
> a local variable in a function that retains its value.
>
> For example, suppose I have:
>
> def set_bit (bit_index, bit_value):
> static bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
> bits [bit_index] = bit_value
>
> print "\tBit Array:"
> int i
> while (i < len(bits):
> print bits[i],
> print '\n'

Many people suggest that using a class for this is the Python idiom (and
perhaps it is), but I prefer to use a decorator for adding attributes to
functions in this case:

def attrs ( **kwds ):
''' taken from PEP 318 '''
def decorate ( f ):
for k in kwds:
setattr ( f, k, kwds [ k ] )
return f
return decorate

@attrs ( bits = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] )
def set_bit ( idx, val ):
set_bit.bits [ idx ] = int ( bool ( val ) )
print "Bit Array:"
for i in set_bit.bits:
print i,
print


>>> set_bit ( 4, 1 )
Bit Array:
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
>>> set_bit ( 5, 1 )
Bit Array:
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0


Regards,
Cliff

Bruno Desthuilliers

unread,
Jul 31, 2006, 4:42:34 PM7/31/06
to
Michael Yanowitz a écrit :

> Is it possible to have a static variable in Python -
> a local variable in a function that retains its value.
>
> For example, suppose I have:
>
> def set_bit (bit_index, bit_value):
> static bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
> bits [bit_index] = bit_value
>
> print "\tBit Array:"
> int i

Syntax error

> while (i < len(bits):
> print bits[i],

Nice infinite loop...

Python's canonical way to iterate over a sequence is the for loop:
for bit in bits:
print bit,

And FWIW, for what you want to do, you don't even need a loop:
print "\n".join(map(str, bits))

> print '\n'


>
> I realize this can be implemented by making bits global, but can
> this be done by making it private only internal to set_bit()? I don't
> want bits to be reinitialized each time. It must retain the set values
> for the next time it is called.

While there are some more or less hackish solutions (cf Roel answers and
my answers to it), the usual way to have functions maintaining state is
to define a class and instanciate it. Note that Python's functions are
objects, and that it's possible to write your own callable objects too
if you really want a function call syntax:

class Setbit(object):
def __init__(self):
self._bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
def call(self, index, value):
self._bits[index] = value
def values(self):
return self._bits[:]

set_bit = Setbit()
set_bit(1, 1)
print "".join(map(str, set_bit.values()))

Cliff Wells

unread,
Jul 31, 2006, 4:37:02 PM7/31/06
to Michael Yanowitz, pytho...@python.org
On Mon, 2006-07-31 at 13:02 -0700, Cliff Wells wrote:


> @attrs ( bits = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] )

Also, IMO, it's a bit more readable to write:

bits = [ 0 for i in range ( 16 ) ]

which avoids the necessity of counting the zeros to know how many there
are.

Regards,
Cliff


--

Cliff Wells

unread,
Jul 31, 2006, 4:43:55 PM7/31/06
to Michael Yanowitz, pytho...@python.org
On Mon, 2006-07-31 at 13:37 -0700, Cliff Wells wrote:
> On Mon, 2006-07-31 at 13:02 -0700, Cliff Wells wrote:
>
>
> > @attrs ( bits = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] )
>
> Also, IMO, it's a bit more readable to write:
>
> bits = [ 0 for i in range ( 16 ) ]

Or even:

bits = [ 0 ] * 16

Just be careful to only use that style when the contents of the array
are non-mutable. The list comp does the right thing in that case (at
risk of going on a tangent):

Right:
>>> bits = [ { } for i in range ( 16 ) ]
>>> bits
[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]
>>> bits [ 0 ][ 'a' ] = 1
>>> bits
[{'a': 1}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]

Wrong:
>>> bits = [ {} ] * 16
>>> bits [ 0 ][ 'a' ] = 1
>>> bits
[{'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}, {'a': 1},
{'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}, {'a': 1},
{'a': 1}, {'a': 1}]
>>>


Regards,
Cliff

Cliff Wells

unread,
Jul 31, 2006, 4:54:45 PM7/31/06
to Michael Yanowitz, pytho...@python.org
On Mon, 2006-07-31 at 15:21 -0400, Michael Yanowitz wrote:
> Is it possible to have a static variable in Python -
> a local variable in a function that retains its value.
>
> For example, suppose I have:
>
> def set_bit (bit_index, bit_value):
> static bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
> bits [bit_index] = bit_value
>
> print "\tBit Array:"
> int i
> while (i < len(bits):
> print bits[i],
> print '\n'
>
>
> I realize this can be implemented by making bits global, but can
> this be done by making it private only internal to set_bit()? I don't
> want bits to be reinitialized each time. It must retain the set values
> for the next time it is called.

BTW, I'm assuming this example was contrived. In real life, I wonder
why you'd ever want to use anything besides:

bits = [ 0 ] * 16

bits [ 4 ] = 1
print "Bit Array:"
print ' '.join ( bits )

Having a "set_bit" function seems redundant when the language syntax
directly supports what you are trying to do.

Regards,
Cliff

--

Paddy

unread,
Jul 31, 2006, 5:00:04 PM7/31/06
to

You can do things with function attributes

def foo(x):
foo.static += x
return foo.static
foo.static = 0

If you are going to set function attributes a lot, then you might like
to addd an attriute setter decorator to your toolbox:

def attributeSetter( **kw):
" decorator creator: initialises function attributes"
def func2(func):
" decorator: initialises function attributes"
func.__dict__.update(kw)
return func
return func2

def accumulator(n):
""" return an accumulator function that starts at n
>>> x3 = accumulator(3)
>>> x3.acc
3
>>> x3(4)
7
>>> x3.acc
7
"""
@attributeSetter(acc = n)
def accum(i):
accum.acc+= i
return accum.acc
return accum


- Paddy

tac-tics

unread,
Jul 31, 2006, 5:11:32 PM7/31/06
to
> But of course:
>
> >>> def fun():
> global x = 10
>
> SyntaxError: invalid syntax
> >>>

global x
x = 10

Close enough ^^;

Michael Yanowitz

unread,
Aug 1, 2006, 7:37:20 AM8/1/06
to pytho...@python.org

-----Original Message-----
From: Cliff Wells [mailto:cl...@develix.com]
Sent: Monday, July 31, 2006 4:55 PM
To: Michael Yanowitz
Cc: pytho...@python.org
Subject: Re: Static Variables in Python?


On Mon, 2006-07-31 at 15:21 -0400, Michael Yanowitz wrote:
> Is it possible to have a static variable in Python -
> a local variable in a function that retains its value.
>
> For example, suppose I have:
>
> def set_bit (bit_index, bit_value):
> static bits = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
> bits [bit_index] = bit_value
>
> print "\tBit Array:"
> int i
> while (i < len(bits):
> print bits[i],
> print '\n'
>
>
> I realize this can be implemented by making bits global, but can
> this be done by making it private only internal to set_bit()? I don't
> want bits to be reinitialized each time. It must retain the set values
> for the next time it is called.

BTW, I'm assuming this example was contrived. In real life, I wonder


why you'd ever want to use anything besides:

bits = [ 0 ] * 16
bits [ 4 ] = 1
print "Bit Array:"
print ' '.join ( bits )

Having a "set_bit" function seems redundant when the language syntax
directly supports what you are trying to do.

Regards,
Cliff

--

Thanks everyone for your help. Yes I know it is contrived. Well it is
as over-simplified version of what I really want. And yes, I do realize
after sending it about the infinite loop in the printing. I tried too
quickly to come up with a good example without testing it first.
I like the class idea, however I realize that the class object itself
has to be global. I will look into the decorators - something which I have
avoided until now.
I tried creating a class, but got an error:

# ********* class BitsClass *****************************************
class BitsClass (object):
def __init__(self, num_bits):
self.bits=[]
for i in range(num_bits):
self.bits.append(0)
def set(self, bit_index, value):
self.bits[bit_index] = value
return self.bits
def get(self, bit_index):
if ((bit_index >= 0) and (bit_index < len(self.bits))):
return self.bits[bit_index]
else:
return scenario_globals.ERROR_
def display(self):
i = 0
while (i < len(self.bits)):
print self.bits[i],
i += 1
print '\n',

global the_bits
the_bits = BitsClass(16)

# inside another function I have:
global the_bits
the_bits.set(index, value)

but I get back:
Traceback (most recent call last):
...
File "scenario_sync.py", line 245, in get_discrete_data
the_bits.set(index, value)
AttributeError: 'DiscreteBits' object has no attribute 'set'

There is

I was also disappointed, I was hoping I could use BitsClass.print()
instead of BitsClass.display().

Cliff Wells

unread,
Aug 1, 2006, 3:43:04 PM8/1/06
to Michael Yanowitz, pytho...@python.org

>>> class BitsClass (object):
... def __init__(self, num_bits):
... self.bits=[]
... for i in range(num_bits):
... self.bits.append(0)
... def set(self, bit_index, value):
... self.bits[bit_index] = value
... return self.bits
... def get(self, bit_index):
... if ((bit_index >= 0) and (bit_index < len(self.bits))):
... return self.bits[bit_index]
... else:
... return scenario_globals.ERROR_
... def display(self):
... i = 0
... while (i < len(self.bits)):
... print self.bits[i],
... i += 1
... print '\n',
...
>>> the_bits = BitsClass(16)
>>> the_bits.set (4, 1)
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]


Works for me. I'm not sure what 'DiscreteBits' in your error refers to.
Also, you don't need to explicitly declare global variables "global".

Regards,
Cliff

--

Slawomir Nowaczyk

unread,
Aug 3, 2006, 4:08:06 PM8/3/06
to Python Mailing List
On Tue, 01 Aug 2006 07:37:20 -0400
Michael Yanowitz <m.yan...@kearfott.com> wrote:

#> I like the class idea, however I realize that the class object itself
#> has to be global.

But no more global than your original set_bit was...

--
Best wishes,
Slawomir Nowaczyk
( Slawomir...@cs.lth.se )

To err is human, but to really fuck things up takes a computer.

Cameron Laird

unread,
Aug 7, 2006, 1:46:53 PM8/7/06
to
In article <1154378719....@p79g2000cwp.googlegroups.com>,
Paddy <padd...@netscape.net> wrote:
.
[substantial thread
with many serious
alternatives]
.
.

>You can do things with function attributes
>
>def foo(x):
> foo.static += x
> return foo.static
>foo.static = 0
.
.
.
My favorite variation is this:

def accumulator(x):
# On first execution, the attribute is not yet known.
# This technique allows use of accumulator() as a
# function without the "consumer" having to initialize
# it.
if not "static" in dir(accumulator):
accumulator.static = 0
accumulator.static += x
return accumulator.static

print accumulator(3)
print accumulator(5)

Paddy

unread,
Aug 8, 2006, 2:00:50 AM8/8/06
to

Thanks Cameron, I'll accumulate this in my toolbox.

- pad.

0 new messages