Toast
Toast

Reputation: 657

Access class from a file imported by the class definition file

This is my not working code (simplified):

File A.py:

from B import *

class A(object):
    def __init__(self):
        A.instance = self
        self.b = B()

    def testA(self):
        print "success"

if __name__ == '__main__':
    a = A()
    a.b.testB()

File B.py:

from A import *

class B(object):
    def testB(self):
        A.instance.testA()

It fails at the last line of B.py: type object 'A' hast no attribute 'instance'. It works if A and B are in the same file. How can I split this into multiple files to prevent having my entire project in one giant file?

Upvotes: 0

Views: 54

Answers (1)

BrenBarn
BrenBarn

Reputation: 251408

When you run A.py, it is considered to have the name __main__ (as used in your if __name__ == '__main__' test). But when B imports A, it has the name A. So the module is loaded twice under different names, and two copies of it exist. When your "main" block runs, it is instantiating the A class from __main__, but B.py only sees the A class from the module A. (See this recent question for a similar issue, and this one for some more description of the double-import problem.)

The solution is to separate out the code you need to import from the file you want to run as a script. Put the classes in separate files A.py and B.py, then have a third file (script.py or whatever) that does whatever it needs to with both files. For instance, your script.py could do:

from A import A

if __name__ == "__main__":
    a = A()
    a.b.testB()

You can then set up A and B like this:

### A.py
import B

class A(object):
    def __init__(self):
        A.instance = self
        self.b = B.B()

    def testA(self):
        print "success"

### B.py
import A

class B(object):
    def testB(self):
        A.A.instance.testA()

Having multiple modules that import each other is in general a risky proposition. If you have multiple classes that need to reference one another, the easiest thing is to keep them in the same module. (If this becomes awkward because you have large numbers of mutually referential classes, you might want to revist your overall design, since large numbers of mutually referential classes can be awkward.)

Upvotes: 1

Related Questions