Python: Circular Imports Needed For Type Checking
Solution 1:
The best solution is to not check types.
The other solution is to not create an instance of, and not reference at all, Foo
or Bar
until both classes are loaded. If the first module is loaded first, don't create a Bar
or refer to Bar
until after the class Foo
statement is executed. Similarly, if the second module is loaded first, don't create a Foo
or reference Foo
until after the class Bar
statement is executed.
This is basically the source of the ImportError
, which could be avoided if you did "import foo" and "import bar" instead, and used foo.Foo
where you now use Foo
, and bar.Bar
where you now use Bar
. In doing this, you no longer refer to either of them until a Foo
or Bar
is created, which hopefully won't happen until after both are created (or else you'll get an AttributeError
).
Solution 2:
You can program against interface
(ABC - abstract base class in python), and not specific type Bar
. This is classical way to resolve package/module inter-dependencies in many languages. Conceptually it should also result in better object model design.
In your case you would define interface IBar
in some other module (or even in module that contains Foo class - depends on the usage of that abc
). You code then looks like this:
foo.py:
from bar import Bar, IFoo
classFoo(IFoo):
def__init__(self):
self.__bar = Bar(self)
# todo: remove this, just sample code
f = Foo()
b = Bar(f)
print f
print b
x = Bar('do not fail me please') # this fails
bar.py:
from abc import ABCMeta
classIFoo:
__metaclass__ = ABCMeta
classBar(object):
def__init__(self, arg_instance_of_foo):
ifnotisinstance(arg_instance_of_foo, IFoo):
raise TypeError()
Solution 3:
You could just defer the import in bar.py like this:
classBar(object):
def__init__(self, arg_instance_of_foo):
from foo import Foo
ifnotisinstance(arg_instance_of_foo, Foo):
raise TypeError()
Solution 4:
Possible duplicate: Python type hinting without cyclic imports
You should use Forward Reference (PEP 484 - Type Hints):
When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later.
So instead of:
classTree:def__init__(self, left: Tree, right: Tree):
self.left = left
self.right = right
do:
classTree:def__init__(self, left:'Tree', right:'Tree'):
self.left = left
self.right = right
Post a Comment for "Python: Circular Imports Needed For Type Checking"