Python - when is 'import' required?
Question
mod1.py
import mod2
class Universe:
def __init__(self):
pass
def answer(self):
return 42
u = Universe()
mod2.show_answer(u)
mod2.py
#import mod1 -- not necessary
def show_answer(thing):
print thing.answer()
Coming from a C++ background I had the feeling it was necessary to import the module containing the Universe class definition before the show_answer function would work. I.e. everything had to be declared before it could be used.
Am I right in thinking this isn't necessary? This is duck typing, right? So if an import isn't required to see the methods of a class, I'd at least need it for the class definition itself and the top level functions of a module?
In one script I've written, I even went as far as writing a base class to declare an interface with a set of methods, and then deriving concrete classes to inherit that interface, but I think I get it now - that's just wrong in Python, and whether an object has a particular method is checked at runtime at the point where the call is made?
I realise Python is so much more dynamic than C++, it's taken me a while to see how little code you actually need to write!
I think I know the answer to this question, but I just wanted to get clarification and make sure I was on the right track.
UPDATE: Thanks for all the answers, I think I should clarify my question now:
Does mod2.show_answer() need an import (of any description) to know that thing has a method called answer(), or is that determined dynamically at runtime?
Solution
import
is all about names -- mostly "bare names" that are bound at top level (AKA global level, AKA module-level names) in a certain module, say mod2
. When you've done import mod2
, you get the mod2
namespace as an available name (top-level in your own module, if you're doing the import
itself as top level, as is most common; but a local import
within a function would make mod2
a local variable of that function, etc); and therefore you can use mod2.foobar
to access the name foobar
that's bound at top level in mod2
. If you have no need to access such names, then you have no need to import mod2
in your own module.
OTHER TIPS
In this case you're right: show_answer() is given an object, of which it calls the method "answer". As long as the object given to show_answer() has such a method, it doesn't matter where the object comes from.
If, however, you wanted to create an instance of Universe inside mod2, you'd have to import mod1, because Universe is not in the mod2 namespace, even after mod2 has been imported by mod1.
Think of import being more like the linker.
With "import mod2" you are simply telling python that it can find the function in the file mod2.py
Actually, in this case, importing mod1
in mod2.py
should not work.
Would it not create a circular reference?
In fact, according to this explanation , the circular import
will not work the way you want it to work: if you uncomment import mod1
, the second module will still not know about the Universe
.
I think this is quite reasonable. If both of your files need access to the type of some specific object, like Universe
, you have several choices:
- if your program is small, just use one file
- if it's big, you need to decide if your files both need to know how
Universe
is implemented, perhaps passing an object of not-yet-known type toshow_answer
is fine - if that doesn't work for you, by all means put
Universe
in a separate module and load it first.
import in Python loads the module into the given namespace. As such, is it as if the def show_answer actually existed in the mod1.py module. Because of this, mod2.py does not need to know of the Universe class and thus you do not need to import mod1 from mod2.py.
I don't know much about C++, so can't directly compare it, but..
import
basically loads the other Python script (mod2.py
) into the current script (the top level of mod1.py
). It's not so much a link, it's closer to an eval
For example, in Python'ish psuedo-code:
eval("mod2.py")
is the same as..
from mod2 import *
..it executes mod2.py, and makes the functions/classes defined accessible in the current script.
Both above snippets would allow you to call show_answer()
(well, eval doesn't quite work like that, thus I called it pseudo code!)
import mod2
..is basically the same, but instead of bringing in all the functions into the "top level", it brings them into the mod2 module, so you call show_answer
by doing..
mod2.show_answer
Am I right in thinking [the import in mod2.py] isn't necessary?
Absolutely. In fact if you try and import mod1
from mod2
you get a circular dependancy error (since mod2
then tries to import mod1
and so on..)