Static Variables in Python?

M

Michael Yanowitz

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,
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
 
R

Roel Schroeven

Michael Yanowitz schreef:
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,
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.


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:
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.
 
T

tac-tics

Michael said:
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,
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.


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.
 
B

bearophileHUGS

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
 
J

John Salerno

tac-tics:

Are you sure?

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

Bye,
bearophile

This works for me:
global x
x = 10


But of course:
global x = 10

SyntaxError: invalid syntax
 
B

Bruno Desthuilliers

Roel Schroeven a écrit :
Michael Yanowitz schreef:
(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.
 
B

Bruno Desthuilliers

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,


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()))
 
P

Paddy

Michael said:
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,
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


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 7
"""
@attributeSetter(acc = n)
def accum(i):
accum.acc+= i
return accum.acc
return accum


- Paddy
 
C

Cameron Laird

.
[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)
 
P

Paddy

Cameron said:
.
[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)

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

- pad.
 
Joined
Jul 10, 2008
Messages
1
Reaction score
0
Your solution does not seem to work

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:

HTML:
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[:]

I get this after running it:
>>> ============= RESTART ================
>>> a = Setbit(1,1)

Traceback (most recent call last):
File "<pyshell#162>", line 1, in -toplevel-
a = Setbit(1,1)
TypeError: __init__() takes exactly 1 argument (3 given)

>>>

Also guys - why don't you use TABS in your post which are fundamental in Python ? I know that INDENT does not work properly on this forum but you can use HTML tag marks : <>
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top