Home > Software design >  Python - Accessing object variables within a module
Python - Accessing object variables within a module

Time:12-03

I have a module (a python file, that is) containing different classes with functions, here called 'Experiment_1'. When running it as the main file, all objects can access all variables - object_2 functions can access variables in object_1, and so on:

# Experiment_1
class A():
    def process1(self):
        self.x=10

    def process2(self):
        self.y=20

class B():
    def addition(self):
        summed=object_1.x object_1.y
        print(summed)

if __name__ == '__main__':
    object_1=A()
    object_2=B()
    
    object_1.process1()
    object_1.process2()

    object_2.addition()

Next, I attempt to run this in file 'Experiment_2' as an imported module:

# Experiment_2
from Experiment_1 import *
import Experiment_1

object_1=A()
object_2=B()

object_1.process1()
object_1.process2()

object_2.addition()

And get the error message:

  File "C:\Program Files\Sublime Text 3\Experiment_2.py", line 10, in <module>
    object_2.addition()
  File "C:\Program Files\Sublime Text 3\Experiment_1.py", line 10, in addition
    summed=object_1.x object_1.y
NameError: name 'object_1' is not defined

Thus, object_2 can no longer access the variables of object_1. I have been searching a lot to find a solution to this but may be using the wrong keywords or simply lack the understanding to recognize the answer when I see it - can anyone give me a hint how to proceed?

Thanks in advance!

CodePudding user response:

The issue is your object instantiation in Experiment_1.py. The code inside the below block only get executed if you run the file as a script and NOT when you import it.

if __name__ == '__main__':
    pass

So in your object of class B, the below statement in addition method,

#Experiment_1.py

summed=object_1.x object_1.y

see object_1 as not defined, because it is only instantiated in the if __name__ == '__main__': block which is not executed when importing the module.

See this question: What does if __name__ == "__main__": do?

And for the solution, If you wish to use the module structure, the work around is to pass the object to the addition method.

#Experiment_1.py
class A():
    def process1(self):
        self.x = 10

    def process2(self):
        self.y = 20


class B():
    def addition(self, obj):
        summed = obj.x   obj.y
        print(summed)

then in your next file,

from Experiment1 import *
# import Experiment1

object_1=A()
object_2=B()

object_1.process1()
object_1.process2()

object_2.addition(object_1)

CodePudding user response:

When you import a module, the block starting with if __name__ == "__main__": does not get executed as the name variable of the module is set to the name you imported it ("Experiment_1" in this case). From official documentation:

When a Python module or package is imported, name is set to the module’s name. Usually, this is the name of the Python file itself without the .py extension

If you'd like your code to get executed regardless of it is imported or run directly from command line, just place it at the bottom.

CodePudding user response:

Not tested, but I think the following script is the solution, because you need to inherit attributes. Test changes (on first module) and give a response, please.

class A():
    def __init__(self):
        self.x = 0
        self.y = 0

    def process1(self):
        self.x=10

    def process2(self):
        self.y=20

class B(A):
    def __init__(self):
        A.__init__(self)

    def addition(self):
        summed = self.x   self.y
        print(summed)

if __name__ == '__main__':
    object_1 = A()
    object_2 = B()
    
    object_1.process1()
    object_1.process2()

    object_2.addition()

Edit

Sorry, I don't realize that B can do all purpose. This is the good solution:

experiment1.py

class A:
    def __init__(self):
        self.x = 0
        self.y = 0

    def process1(self):
        self.x = 10

    def process2(self):
        self.y = 20


class B(A):
    def __init__(self):
        A.__init__(self)

    def addition(self):
        summed = self.x   self.y
        print(summed)


if __name__ == '__main__':
    object_1 = B()

    object_1.process1()
    object_1.process2()

    object_1.addition()

experiment2.py

from Experiment1 import *

if __name__ == '__main__':
    object_1 = B()
    object_1.process1()
    object_2.process2()

    object_2.addition()

Explaination: because B class inherits methods and attributes of A class, you don't need instantiate A class. All the work can be run by B class.

As other user said, in B class you are using global variable declared in main section that is unreachable when you import module, this is the principle of the if __name__ == '__main__':

  • Related