<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Apr 4, 2013 at 2:36 AM, Kristján Valur Jónsson <span dir="ltr"><<a href="mailto:kristjan@ccpgames.com" target="_blank">kristjan@ccpgames.com</a>></span> wrote:<br>
[...]<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
There can be good and valid reasons to put things that depend on each other in separate modules, for example when trying to separate modules by functionality or simply when splitting a long file into two.<br>
Notice that cyclic dependencies are allowed _within_ a module file. Imagine if we decided that we could only refer to objects _previously_ declared within a .py file, because it encouraged the good design practice of factoring out common dependencies.<br>
Dependency graphs of software entities can sadly not always be reduced into a DAG, and we should, IMHO, by no means force people to keep each cygle in the dependency graph within a single .py module.<br clear="all"></blockquote>
<div><br></div><div>IMO in both cases (cyclic dependencies within modules and between modules) Python's approach is consistently derived from a specific implementation strategy: names are available after they are defined. This works (at least it doesn't raise NameError :-):<br>
</div><div><br></div><div>def f(): return g()<br></div><div>def g(): return f()<br></div><div>f()<br></div><div><br></div><div>Because by the time f() is called, g() is defined. Note that this doesn't work:<br><br>def f(): return g()<br>
</div><div>f()<br></div><div>def g(): return f()<br><br></div><div>IOW there is no magic. If you think of putting objects in a dictionary, the semantics are clear. (Except for the shenanigans that the compiler carries out for determining whether something is a local variable reference or not, but that's also explainable.)<br>
</div><div><br></div><div>This does not work:<br><br></div><div>a = b<br>b = a<br><br></div><div>because the first line references b which is not yet defined.<br></div><div><br></div><div>Similarly, if module A imports module B and B imports A, that works because imports are first satisfied from sys.modules, and when A is loaded, it is entered into sys.modules before its code is executed. But it may be that if A is loaded and starts importing B, B is then loaded and imports A, which finds A in the state it reached when it decided to import B. The rules here are more complicated because of what "from A import X" means (it depends on whether X is a submodule or not) but there are rules, and they are totally well-defined. The final piece of this puzzle is that, given A and B mutually importing each other, the top-level app code could start by importing A or B, and the execution order will be different then. (You can force this by putting A and B in a package whose __init__.py imports them in the desired order.)<br>
<br></div><div>I don't really see what we could change to avoid breaking code in any particular case -- the burden is up to the library to do it right. I don't see a reason to forbid any of this either.<br></div>
</div>
<br>-- <br>--Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)
</div></div>