How to initialize a class variable once

R

Roy Smith

I've got a class with a class variable:

class Foo:
_map = {}

How do I make sure this only gets initialized the *first* time the
module containing the class is imported? What appears to be happening
as it stands is each time the module gets imported, Foo._map get re-
initialized.
 
M

Matimus

I've got a class with a class variable:

class Foo:
   _map = {}

How do I make sure this only gets initialized the *first* time the
module containing the class is imported?  What appears to be happening
as it stands is each time the module gets imported, Foo._map get re-
initialized.

Unless you are calling reload() on the module, it will only ever get
_loaded_ once. Each additional import will just yield the existing
module. Perhaps if you post an example of the behavior that leads you
to believe that the class variables are getting reinitialized I can
provide more useful help.

Matt
 
A

alex23

I've got a class with a class variable:

class Foo:
   _map = {}

How do I make sure this only gets initialized the *first* time the
module containing the class is imported?  What appears to be happening
as it stands is each time the module gets imported, Foo._map get re-
initialized.

What you're asking for is actually the default behaviour. The Foo
class should only be created once, on the first import, and all
subsequent imports should refer to it:

foo.py:
class Foo:
_map = {}

a.py:
from foo import Foo
Foo._map['a'] = 1

b.py:
from foo import Foo
print Foo._map

c.py:
import a
import b

This outputs "{'a': 1}", as expected. The Foo._map that b.py prints is
the same Foo._map that a.py has modified.

You might need to provide some more details about your code.
 
J

John Machin

Unless you are calling reload() on the module, it will only ever get
_loaded_ once. Each additional import will just yield the existing
module. Perhaps if you post an example of the behavior that leads you
to believe that the class variables are getting reinitialized

and change it to
class Foo(object):
because we care little about old-style classes these days
and put a print statement in the module just before the class
statement and print statements before and after each import statement
so that we can see what is happening.
 
J

Joe Strout

There is one situation where a module can be imported/executed
twice, if it is the __main__ module.

That's an excellent point -- this is something I've run into, and it
always feels a bit awkward to code around it. What's the standard
idiom for avoiding this issue in a complex app? Have a "main" file
that is not imported by anything else, and which does little but
launch stuff from some other module?

As I say it, that seems obvious, but somehow I keep getting urges to
put global stuff (like my Application subclass) in the main file, and
then I find I need to reference it from some other module, and get
into trouble. This is probably just bias from my last programming
environment, though. I can adapt.

Anyway, thanks for pointing this out; I bet it's the root cause of the
OP's observation.

Best,
- Joe
 
G

George Sakkis

That's an excellent point -- this is something I've run into, and it  
always feels a bit awkward to code around it. What's the standard  
idiom for avoiding this issue in a complex app?  Have a "main" file  
that is not imported by anything else, and which does little but  
launch stuff from some other module?

Yes, I believe that's the common practice. Still, whenever I end up
putting stuff in a "main" file and run into the double import problem
(e.g. when pickling), I do an explicit "from main import *" after all
the definitions, i.e.:

# myscript.py

__all__ = ['foo', 'Bar']

def foo(x,y):
...

class Bar(object):
....

from myscript import *

if __name__ == '__main__':
assert foo.__module__ == Bar.__module__ == 'myscript'


George
 
R

Roy Smith

Anyway, thanks for pointing this out; I bet it's the root cause of the
OP's observation.

Wow, good diagnosis! This was happening in a test framework (using
unittest). I had a class which had a @staticmethod factory function, and a
class member dict where __init__() registered every instance of the class
that got created.

Something was going wrong, so in my test code (i.e. in __main__), I
imported the module directly and printed the dict. Lo and behold, it was
empty! As far as I could tell,

class Foo:
_map = {}

was getting executed again, which made no sense. I even went as far as
printing out id(Foo) in both places to make sure I really had the same
class (I did).

Thanks for the help. I never would have figured this out on my own.
 

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

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top