I want to construct an object from the same class in one of its methods. However, the method is in a different file. How can I do the following?
file1.py
class MyClass():
def __init__(self, i):
print(i)
from file2 import my_fun
file2.py
def my_fun(self):
if i == 1:
new_obj = MyClass(i + 1)
I get the following error:
NameError: name 'MyClass' is not defined
file2
has to import file1.MyClass
somewhere. Importing inside my_fun
is of course possible, but not desirable. Doing from file1 import MyClass
at the beginning of the file will cause a circular dependency problem: MyClass
may not have been executed yet at that point, and so may not exist.
Option 1:
import file1
def my_fun(self):
if i == 1:
new_obj = file1.MyClass(i + 1)
In this case, file1
will refer to the correct module object, even if its __dict__
is not completely filled in at that point. By the time my_fun
can be called, file1
will have been loaded completely.
Option 2:
class MyClass():
def __init__(self, i):
print(i)
from file2 import my_fun
MyClass.my_fun = my_fun
del my_fun
def my_fun(self):
if i == 1:
new_obj = MyClass(i + 1)
from file1 import MyClass
In this version, you place all the import statements after definitions of things imported to another file have had a chance to run. This is not very elegant at all.
Option 3
def my_fun(self):
from file1 import MyClass
if i == 1:
new_obj = MyClass(i + 1)
This is the ugliest option of all. You remove the circular dependency by removing file2
's dependency on file1
. The dependency is exclusive to my_fun
, and does not manifest itself until runtime, when it is totally resolvable. This is not that terrible because after the first execution, the import is basically just assigning
MyClass = sys.modules['file1'].MyClass
TL;DR
You have a couple of ways of bypassing circular dependencies by carefully working around the execution paths of module loading. However, all options shown here are code smell, and you should avoid them. They indicate an inappropriate level of coupling between the modules that should be resolved in other ways.