user847988
user847988

Reputation: 984

How do I access inherited variables from another module when they are changed in parent?

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

Answers (4)

Nafiul Islam
Nafiul Islam

Reputation: 82470

a.py

avariable = None

class a():

    def method(self):
        global avariable
        avariable = 100
        print "variable is", avariable

b.py

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()

Output:

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.

EDIT

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

Ashwini Chaudhary
Ashwini Chaudhary

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:

a.py

x = 'a'
def func():
    global x
    print x

b.py:

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:

a.py

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

b.py

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

Alfe
Alfe

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

fjarri
fjarri

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 ids 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

Related Questions