goocreations
goocreations

Reputation: 3066

Python - Static Class Variables

I'm from a C++ background and have often been using static vars to reduce the number of time variables have to be initialized (especially if the initialization takes very long). So from other posts on StackOverflow, people suggested using static class variables as follows:

class MyClass(object):

    StaticList1 = [...] # Very large list
    StaticList2 = [...] # Very large list

Now this is fine if there exists at least 1 instance of MyClass throughout the execution of the program and the lists are only created once. However, if at some stage of the execution there is no instance of MyClass, Python seems to remove the static lists (I assume because the reference counter drops to 0).

So my question, is there any easy way without using external modules to initialize StaticList1 and StaticList2 only once (the first time they are used) and never to remove them even if there is no instance of MyClass until the program exists (or you delete the lists manually)?

EDIT:

Maybe I oversimplified this issue. What I'm doing:

class MyClass(object):

    StaticList = None

    def __init__(self, info):
        if self.StaticList == None:
            print "Initializing ..."
            self.StaticList = []
            # Computationally expensive task to add elements to self.StaticList, depending on the value of parameter info

    def data(self):
        return self.StaticList

I import the module from another script and have a loop like this:

import myclass
for i in range(10000):
    m = myclass.MyClass(i)
    d = m.data()
    # Do something with d.

The initializing of the static list takes about 200 - 300 ms and is executed on every iteration of the loop, so the loop takes extremely long to finish.

Upvotes: 2

Views: 4794

Answers (1)

Hans
Hans

Reputation: 2615

While your class does have a static field called StaticList, you are actually initializing and working with an instance field of the same name because of the self qualifier you are using. I think your code will work fine if you use MyClass.StaticList to initialize and access it instead.

In general, by Python's name lookup, you can access a class field via an instance as if it was an instance field (e.g., self.StaticList) on that instance as long as you haven't actually set an instance field of the same name on that instance. From that moment on, the instance field shadows the class field (i.e., self.StaticList will find your new value, while MyClass.StaticList will still refer to your class value).

As an example fresh from the interpreter:

>>> class A(object):
...  v=2      # static initialization
...
>>> A.v
2
>>> a=A()     # get an instance, and
>>> a.v       # get the static value via the instance:
2
>>> a.v = 7   # but now set 'v' on the instance, and ...
>>> a.v       # we will get the instance field's value:
7
>>> A.v       # the static value is still the old:
2
>>> b=A()     # and other instances of the class ...
>>> b.v       # will use the same old static value:
2

The instance variable a.v is initially equal to A.v, but by explicitly setting a.v=7, you are "dissociating" them in that instance.

While this means that, in principle, you could make use of a static class field MyClass.Values as well as an instance field xyz.Values of the same name, this is often discouraged for exactly this kind of confusion.

As a separate remark, you could consider annotating the data method as a @staticmethod (and remove the self argument in the move) and call it as MyClass.data() to make the fact clearer that you would be getting back the same list instance on every call.

Upvotes: 5

Related Questions