Impersonating a Static Variable in Python

vegaseat 0 Tallied Votes 595 Views Share

If you want a variable in a C function to retain its last assigned value, you simply declare it as static. Python does not have static variables, but you can impersonate one in different ways. The default list argument is my preferred option. Here are some examples.

# mimic a static variable to count how many times a function or method has been called
# (static comes from C, where a static variable in the function retains its last value)
# tested with Python24 by      vegaseat     29may2006

# using a global variable:
def static_num1() :
   global x
   x += 1
   return x

x = 0                # x increases with each call
print static_num1()  # 1
print static_num1()  # 2
print static_num1()  # 3
    
print "-"*30

# like a global variable but a little safer, use function.attribute:
def static_num2():
    static_num2.x += 1
    return static_num2.x

static_num2.x = 0    # at least you know the function x is used for
print static_num2()  # 1
print static_num1()  # 2
print static_num1()  # 3

print "-"*30

# use a mutable object like a list element as default argument:
def static_num3(list1=[0]):
    """The function's default is a list with one element = zero.
    Since the list is a mutable object it retains its address,
    as the function's default is created at compile time.
    Whatever you put into this list as element is retained too"""
    list1[0] += 1
    return list1[0]

print static_num3()  # 1
print static_num3()  # 2
print static_num3()  # 3

print "-"*30

# use a generator function (yield replaces return):
def static_num4():
    k = 0
    while True:
       k += 1
       yield k

static4 = static_num4().next  # next is needed with generator functions

print static4()  # 1  () is needed for call
print static4()  # 2
print static4()  # 3

print "-"*30

# use a class and classmethod():
class Static5:
    k = 0
    def count(self):
        self.k += 1
        return self.k
    # this allows you to simply call Static5.count()
    count = classmethod(count)
    
print Static5.count()  # 1
print Static5.count()  # 2
print Static5.count()  # 3

print "-"*30

# same idea with @decorator:
class Static6:
    k = 0
    # allows you to simply call Static6.count()
    @classmethod
    def count(self):
        self.k += 1
        return self.k

print Static6.count()  # 1
print Static6.count()  # 2
print Static6.count()  # 3

print "-"*30

# example of using the default list as a counter in a function:
def f1(str1, count=[0]):
    # your code
    str1 = str1 + " and butter"
    # the counter
    count[0] += 1
    # return a tuple
    return count[0], str1

print f1("bread")  # (1, 'bread and butter')
print f1("bread")  # (2, 'bread and butter')
print f1("bread")  # (3, 'bread and butter')

print "-"*30

# another example, you could make up all the lyrics from 99 on down:
def beer(count=[100]):
    # the counter
    count[0] -= 1
    # your code
    str1 = str(count[0]) + " bottles of beer on the wall ..."
    return str1

print beer()  # 99 bottles of beer on the wall ...
print beer()  # 98 bottles of beer on the wall ...
print beer()  # 97 bottles of beer on the wall ...