0

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!

Henry
  • 3
  • 2
  • Because in that case, `object_1` is **not** defined, that is the whole point of `if __name__ == "__main__":` – juanpa.arrivillaga Dec 02 '21 at 08:04
  • Your method probably shouldn't reference some random name that it assumes is some random instance that should exist in the global scope, this goes against the whole point of OOP, which is to *encapsulate state*, not rely on global state! – juanpa.arrivillaga Dec 02 '21 at 08:05

3 Answers3

0

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.

0

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)
All Іѕ Vаиітy
  • 24,861
  • 16
  • 87
  • 111
  • Thanks a million! Time for me to dig into all of your proposed solutions - this community is a gold mine :) – Henry Dec 02 '21 at 08:28
-1

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__':

Winter Squad
  • 169
  • 7
  • The reason is explained by other users. In Class B you are using global variable declared in _main section_ that will not imported by experiment2.py because this part of code is unreachable. This is the purpose of this _section_. – Winter Squad Dec 02 '21 at 08:38
  • 1
    Thanks for your valuable input! There is something I do not understand about modules, clearly. I was under the impressions that importing basically was to copy in the code from the imported file (although the lines are hidden), and the functions would then be accessible as if written in the main file. – Henry Dec 02 '21 at 08:46
  • The answer you've accepted can be a pleasant solution, but if B inherits A, you will not need to pass any argument to addition method. I like the other solution, and I accept I was lazy. – Winter Squad Dec 02 '21 at 08:54
  • 1
    I have now accepted your answer as well. There is good stuff for me to learn from it. – Henry Dec 02 '21 at 09:22