Reputation: 984
I have a file a.py
avariable = None
class a():
def method(self):
global avariable
avariable = 100
print "variable is", avariable
and a file b.py
from a import *
class b(a,):
def mymethod(self):
a().method()
print "avariable is " , avariable
if __name__ == '__main__':
b().mymethod()
File b
imports everything from a
and also inherits from a
.
a
's method
is called and the avariable
is change to 100 but when I print avariable
in b the value is None
. How to I use in class b
the variable avariable
that a
class changed?
Output:
>python b.py
variable is 100
avariable is None
Clarification
It's crucial for me to use
from a import *
because I have already code in class b that calls methods of class a using the syntax
self.method()
and that cannot change.
i.e.
from a import *
class b(a):
def mymethod(self):
self.method()
print "avariable is " , avariable
if __name__ == '__main__':
b().mymethod()
So is there a way to access the variable avariable
in a without prefixing in any way the
avariable
?
Upvotes: 4
Views: 3255
Reputation: 82470
avariable = None
class a():
def method(self):
global avariable
avariable = 100
print "variable is", avariable
import a
class b(a.a):
def mymethod(self):
a.a().method()
print "avariable is ", a.avariable
if __name__ == '__main__':
print a.avariable
b().mymethod()
b().mymethod()
None
variable is 100
avariable is 100
variable is 100
avariable is 100
You get None
all the time because once you import avariable
you keep it in your own file, but what a.py
is changing, is the avariable
variable in its own file (or more appropriately, its own global namespace), and thus, you can see no change.
But in the example above, you can see the changes. This is because, we are importing the a
module itself, and thus accessing all its objects (everything in Python is an object). And thus, when we call a.avariable
we are actually calling the avriable
variable in a
's global namespace.
The code below will still produce the same output.
import a
class b(a.a):
def mymethod(self):
self.method()
print "avariable is ", a.avariable
if __name__ == '__main__':
print a.avariable
b().mymethod()
b().mymethod()
Upvotes: 4
Reputation: 250921
Global variables in a module are global to that module only, not in the imported module.
So, when you call a().method()
in b.py, global avariable
actually modifies the a's avariable
not b
.
i.e You can't access a
's global namespace by using global
in b.py
.
Example:
x = 'a'
def func():
global x
print x
from a import *
x = 'b' #override `x` imported from `a`
func() #call to func() prints 'a' not 'b'
print x #prints 'b'
The call to func()
actually access a
's x
not the current x
so it prints 'a'
and print x
in b.py
prints 'b' as expected.
Output:
a
b
Read: Python - Visibility of global variables from imported modules
Instead of using global variables you can use class attributes:
class a(object):
variable = None
def method(self):
a.avariable = 100 #modification to `a`'s attribute will be seen in `b()`
print "variable is", a.avariable
from a import *
class b(a):
def mymethod(self):
a().method()
print "avariable is " , self.avariable
if __name__ == '__main__':
b().mymethod()
output:
variable is 100
avariable is 100
Upvotes: 1
Reputation: 59426
By importing a module defining a variable directly (as is avariable
in module a
in your example), you will get a second variable in your importing module. The two variables are not the same (a.avariable is not b.avariable
).
You can access the other module's variable by using more qualified naming schemes (as displayed in the answer of @Games Brainiac).
The keyword global
declares a variable as module-global. Python has no concept of truly global variables which are the same for each module. (Correct me if I'm wrong here but I never found such a thing yet.)
Upvotes: 1
Reputation: 9726
First, inheritance has nothing to do with it, and only complicates your example. You could have demonstrated your point with only a single function in a.py
.
Anyway, when you write from a import *
, Python goes over all public variables in a
, and updates the dictionary of the module b
as (very simplified):
import a
for name in a.__dict__:
locals()[name] = a.__dict__[name]
So the contents of avariable
just gets copied, and when you print it in b.py
, you are printing a different variable (you can check it by printing the id
s too).
To do what you want your b.py
has to look like
import a
class b(a.a,):
def mymethod(self):
a.a().method()
print "avariable is " , a.avariable
if __name__ == '__main__':
b().mymethod()
so that you are actually accessing the same avariable
.
But having said that, it is an absolutely terrible practice. Non-constant global variables in modules can lead to all sorts of weird and hard to detect bugs.
Upvotes: 1