Bug in Python class static variable?

B

Bruza

I am trying to define a class static variable. But the value of the
static variable seems to be only defined inside the file that the
class is declared. See the code below. When I run "python w.py", I
got:

000=======> Hello World
001=======> Hello World
002=======> Not Initialized
003=======> Not Initialized
004=======> Not Initialized
005=======> Hello World

Looks like even though the class variable "ClassW.w_classStaticVar"
was set inside "startup()", the value never carried over to functions
in "a.py". Is this a bug in Python's static variable handling. I am
running Python 2.4.4.


Ben


#===== file: w.py ========
from a import *

class ClassW:
w_classStaticVar = "Not Initialized"

def initA(self):
print "001=======>", ClassW.w_classStaticVar
obj = ClassA()
obj.init2()
print "005=======>", ClassW.w_classStaticVar

def startup():
ClassW.w_classStaticVar = "Hello World"
wo = ClassW()
print "000=======>", ClassW.w_classStaticVar
wo.initA()

if __name__ == '__main__':
startup()

#===== file: a.py ========
from w import *

class ClassA:
def __init__(self):
print "002=======>", ClassW.w_classStaticVar

def init2(self):
print "003=======>", ClassW.w_classStaticVar
w = ClassW()
print "004=======>", ClassW.w_classStaticVar
 
D

Duncan Booth

Bruza said:
I am trying to define a class static variable. But the value of the
static variable seems to be only defined inside the file that the
class is declared. See the code below. When I run "python w.py", I
got:

When you run "python w.py" the *script* w.py is loaded as the module
__main__. Importing a module called 'w' creates a new module which is
unrelated to __main__. If you want access to variables defined in the main
script then you need to import __main__.

Don't use 'from module import *':

The import statements are executed when the interpreter reaches them in the
source. Even if you fix your code to import from __main__, the values you
try to import from __main__ won't exist when the import statement executes:
the first 'from a import *' will load and execute all of module 'a', but
when that executes 'from __main__ import *' it just imports names defined
in the main script *before* a was imported.

In general, don't try to do this: put all your classes into modules and
just put minimal startup code into a script.
 
B

Bruza

When you run "python w.py" the *script* w.py is loaded as the module
__main__. Importing a module called 'w' creates a new module which is
unrelated to __main__. If you want access to variables defined in the main
script then you need to import __main__.

Don't use 'from module import *':

The import statements are executed when the interpreter reaches them in the
source. Even if you fix your code to import from __main__, the values you
try to import from __main__ won't exist when the import statement executes:
the first 'from a import *' will load and execute all of module 'a', but
when that executes 'from __main__ import *' it just imports names defined
in the main script *before* a was imported.

In general, don't try to do this: put all your classes into modules and
just put minimal startup code into a script.

Duncan,

Thanks for replying. However, I am still confused...
Even if I put "from __main__ import *" in both "a.py" and "w.py", I
still got
the same results. So, how should I re-structure my program to make the
class
static variable works???

Thanks,

Ben
 
D

Duncan Booth

Bruza said:
Duncan,

Thanks for replying. However, I am still confused...
Even if I put "from __main__ import *" in both "a.py" and "w.py", I
still got
the same results. So, how should I re-structure my program to make the
class
static variable works???
Option 1:
In w.py put:

import a

and then refer to a.ClassA

In a.py put:

import __main__

and then refer to __main__.ClassW

But better, option 2:

Create a new file script.py which contains:

import w
if __name__=='__main__':
w.startup()

then in a use 'import w' and in w use 'import a' and refer to a.ClassA and
w.ClassW as above.

Try to think through the order in which Python interprets your code:
remember everything is interpreted. Both 'import' statements and 'class'
statements are really just variation on an assignment, so none of the names
exist until the lines which declare them have been executed. A line 'import
a' is roughly the same as:

a = __import__(something)

and a statement such as 'class ClassA: whatever' is roughly the same as:

ClassA = type('ClassA', baseclasses, dict)

You should never attempt to use the 'from X import *' form of import when
you have modules which include each other (you might get away with it if
you move the imports to the end of the module instead of the beginning, but
it is much simpler just to import the modules, and good practice in any
case).
 
B

Bruza

Option 1:
In w.py put:

import a

and then refer to a.ClassA

In a.py put:

import __main__

and then refer to __main__.ClassW

But better, option 2:

Create a new file script.py which contains:

import w
if __name__=='__main__':
w.startup()

then in a use 'import w' and in w use 'import a' and refer to a.ClassA and
w.ClassW as above.

Try to think through the order in which Python interprets your code:
remember everything is interpreted. Both 'import' statements and 'class'
statements are really just variation on an assignment, so none of the names
exist until the lines which declare them have been executed. A line 'import
a' is roughly the same as:

a = __import__(something)

and a statement such as 'class ClassA: whatever' is roughly the same as:

ClassA = type('ClassA', baseclasses, dict)

You should never attempt to use the 'from X import *' form of import when
you have modules which include each other (you might get away with it if
you move the imports to the end of the module instead of the beginning, but
it is much simpler just to import the modules, and good practice in any
case).

Duncan,

Thanks for the reply; both approaches worked!! Looks like the problem
is because
of "ClassW" is defined in the default "__main__" module, not the "w"
module as
I thought.

I also figured out a 3rd approach adding the following code in "w.py".
The idea
is that I force the program to import "w.py" as "w" if "w.py" is
loaded into
"__main__". Then I can run the qualified "w.startup()". And it also
works :)...

if __name__ == '__main__':
import w
w.startup()
 

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,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top