Discussion:
How to initialize a class variable once
John Machin
2008-12-09 04:44:53 UTC
Permalink
? ?_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
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.
Roy Smith
2008-12-10 00:58:18 UTC
Permalink
In article <mailman.5289.1228837023.3487.python-list at python.org>,
There is one situation where a module can be imported/executed
twice, if it is the __main__ module.
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.
Benjamin Kaplan
2008-12-09 05:04:32 UTC
Permalink
Post by John Machin
_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
and change it to
because we care little about old-style classes these days
unless the OP is using Python 3 in which case that would be redundant. This
is going to be really confusing unless every poster lists their python
version.
Post by John Machin
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.
--
http://mail.python.org/mailman/listinfo/python-list
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20081209/65302453/attachment.html>
alex23
2008-12-09 04:39:34 UTC
Permalink
? ?_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.
Roy Smith
2008-12-09 05:50:26 UTC
Permalink
In article
<707edf86-c223-4cf5-b6ca-a7c396a5edce at t26g2000prh.googlegroups.com>,
Post by alex23
You might need to provide some more details about your code.
It's going to take me some time to generate a minimal test case.
Roy Smith
2008-12-09 04:08:04 UTC
Permalink
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.
Joe Strout
2008-12-09 15:36:50 UTC
Permalink
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
George Sakkis
2008-12-09 16:31:41 UTC
Permalink
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?
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
Brian Allen Vanderburg II
2008-12-09 11:31:12 UTC
Permalink
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
--
http://mail.python.org/mailman/listinfo/python-list
There is one situation where a module can be imported/executed twice, if
it is the __main__ module. Obviously the example below would be
considered bad Python practice but it just shows how it can be done:

main.py:

class Blah(object):
def action(self):
print "action"

print "import"

if __name__ == "__main__":
import app
app.run()


app.py:

def run():
import main
blah = main.Blah()
blah.action()


python main.py:

import
import
action

The reason is the first time main.py gets loaded, it is known as
'__main__' but when app imports main, it is not in sys.modules so it
loads 'main.py' again but this time as 'main'

Brian Vanderburg II


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20081209/8545b62f/attachment.html>
Matimus
2008-12-09 04:36:17 UTC
Permalink
? ?_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

Loading...