Reputation: 3066
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
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