2

I'm trying to work with circular dependency on python (yes, it is needed because I need to separate my models on different files and modules).

I tried several ways to approach this (most of them already suggested by related questions) but none of them resolved the problem. Note: when a remove the circular dependency, the code works.

  1. defer import

    /module_a/class_a.py

    from module_b.class_b import B
    
    class A:
        b = B()
    

    /module_b/class_b.py

    class B:
        from module_a.class_a import A
        a = A()
    
  2. defer both imports

    /module_a/class_a.py

    class A:
        from module_b.class_b import B
        b = B()
    

    /module_b/class_b.py

    class B:
        from module_a.class_a import A
        a = A()
    
  3. not using from .. import notation

    /module_a/class_a.py

    import module_b.class_b as mb
    
    class A:
        b = mb.B()
    

    /module_b/class_b.py

    import module_a.class_a as ma
    class B:
        a = ma.A()
    
  4. not using from .. import notation with defer import

    /module_a/class_a.py

    class A:
        import module_b.class_b as mb
        b = mb.B()
    

    /module_b/class_b.py

    class B:
        import module_a.class_a as ma
        a = ma.A()
    

The result is that none of the solutions worked. I don't know if it has to do with the fact that the call is on the class definition, but it needs to be this way cause I'm using an ORM.

chepner
  • 497,756
  • 71
  • 530
  • 681
Douglas Ramos
  • 531
  • 1
  • 5
  • 10
  • Whether you use `import ...` or `from ... import ...` is irrelevant; both have to import the module, and the latter simply replaces the need for an assignment like `a = module.a` after the import. What exactly "doesn't work"? – chepner May 11 '19 at 20:47
  • I'm getting either the "ImportError: cannot import name 'A' from 'module_a.class_a'" or the "AttributeError: module 'module_a.class_a' has no attribute 'A' – Douglas Ramos May 11 '19 at 20:52
  • Putting the `import` statements inside the classes (in either form) doesn't defer them. They occur as the `class` definition is executed. – martineau May 11 '19 at 21:12

1 Answers1

2

What you are trying to do simply cannot be done that way in Python. Since class definition are mutually reliant on class existence of another other class, neither class can be successfully defined without the other. Even in the same file, this would fail :

class A:
    b = B()
class B:
    a = A()

 NameError: name 'B' is not defined

Circular dependency is anyway considered result of a bad design and can always be avoided by using a different class design. Consider asking a more specific question on how to refactor if this is causing you trouble.

Diane M
  • 1,503
  • 1
  • 12
  • 23
  • I see. In that case, what is the approach to work with one-to-many relationship between models on different files? – Douglas Ramos May 11 '19 at 21:31
  • @DouglasRamos From [this question](https://stackoverflow.com/questions/6928692/how-to-express-a-one-to-many-relationship-in-django) it seems you would declare a ForeignKey in the class that is on the "many" end, and optionally declare a `related_name`. Then Django handles the magic of being able to access the "many" class in the "one" class through a set, without your "one" class to be explicitly referencing it (and thus wouldn't need to import the module). – Diane M May 12 '19 at 00:58