Addind imports to a class namespace
davea at ieee.org
Sat Jul 11 13:56:04 EDT 2009
Ryan K wrote:
> Thanks for your help Peter.
> I'm thinking that perhaps this isn't a circular import and that I
> don't understand importing. Here is a better explanation of my case (I
> am using Django):
> I have file x.py that declares classes A, B, C.
> There is also a file y.py that contains two methods T, U and the class
> that we are talking about above.
> x.py uses a dispatcher system to connect a signal to methods T and U
> in y.py so it does: from y import T, U.
> y.py needs to use classes A, B, C which is basically Menu and Link
> (and some other class) above so I am thinking that if in y.py I have
> from x import A, B, C that will cause a circular import?
> Is this not correct and if it isn't can you explain why? Does using
> from ... import X, Y, Z, i.e. explicit imports avoid this problem or
> does it exacerbate it?
You indeed have described a circular import. In this case, a mutual
dependency exists between x.py and y.py. This can and nearly always
should be avoided. That's independent of the language involved, in any
language, circular dependencies are a code smell
Now, in Python in particular, first question is whether either x.py or
y.py is your main script module (the one where you do the if __name__ ==
"__main__" and the answer is yes). If so, you're in big trouble, and
you really need to rework it. I could elaborate if needed, but trust
me, you don't want to do this, even if it means writing one more module
containing a single import line and just two or three more, and letting
that be your script.
If that's not the case, next question is whether either module refers to
the other one at import time, or only from inside def and class
definitions. If you have any top-level code going on, other than
imports, and this code actually uses a symbol from the other module,
you're probably in trouble. Not as bad as first case, but still worth
avoiding. Sometimes this can be kludged past, by reordering things a
little bit, maybe by moving one of the imports further down in the file.
Now back to the code smell. If the modules really depend on each other,
you should consider factoring out those dependencies and move them to a
third module that both import. Figure out why the modules are broken up
in the particular way they are, and how you can eliminate circular
references by refactoring. It's hard for me to come up with general
principles, but perhaps an example or three will help.
If a callee needs configuration information stored in globals of the
caller, then you probably need to add that config information as parameters.
If an object needs a reference to functions in another module, add them
when constructing the object, not statically.
Or maybe even have the one module explicitly set global variables in the
other module, so they're in one place, instead of being only in the
namespace of the code initializing them.
That's the best I can do without something concrete to adjust.
More information about the Python-list