Maverick
Maverick

Reputation: 376

How to resolve circular dependency when using composition?

I came across some situation like shown below, where each class needs the other class and it creates the cyclic dependency. I came across this type of situation while wrapping some C code using ctypes. There already are lots of post on this topic but I didn't find them helpful, I need some example.

Module A:

from B import C2

class C1(object):
    def __init__(self):
        self.name = "C1"
        self.c2 = C2()

Module B

from A import C1

class C2(object):
    def __init__(self):
        self.name = "C2"
        self.c1 = C1()

Main

from A import C1

if __name__ == "__main__":
    o = C1()
    print(o.name)

Upvotes: 0

Views: 6244

Answers (4)

Harshdeep Khatke
Harshdeep Khatke

Reputation: 131

As it is a Circular import error, remove the import statement from MODULE B -> "from A import C1".

import 'C1' where you need(inside the method).

Like this - from B import C2

class C1(object):

def __init__(self):
    self.name = "C1"
    self.c2 = C2()

class C2(object):

def __init__(self): 
    import A.C1
    self.name = "C2"
    self.c1 = C1()

Upvotes: 0

Tony Hopkinson
Tony Hopkinson

Reputation: 20320

That's a circular dependancy in any language, in fact it's an infinite recursion

Take c2 out of c1 and c1 out of c2

from B import C2 
from A import C1

class C3(object):
  def __init__(self):         
    self.c1 = C1() 
    self.c2 = C2()

Upvotes: 1

Sven Marnach
Sven Marnach

Reputation: 601659

Solutions (assuming the inifinite recursion is resolved):

  1. Avoid this kind of circular dependency.

  2. Put the interdependent components into the same module.

  3. Use import A and import B instead of the from ... form. (This might fail in certain situations if packages are involved.)

  4. Use function-level imports.

Upvotes: 5

Martijn Pieters
Martijn Pieters

Reputation: 1121972

Change Module B to not import class C1 until the last possible moment, inside the __init__.py:

class C2(object):
    def __init__(self):
        from A import C1
        self.name = "C2"
        self.c1 = C1()

Note that because C1 instantiates C2 and vice-versa, you'll end up with an infinite recursion problem, but I'll charitably assume that you don't have that problem outside of your illustration example.

Upvotes: 2

Related Questions