Is `import module` better coding style than `from module import function`?

Viewed 5072

Let from module import function be called the FMIF coding style.

Let import module be called the IM coding style.

Let from package import module be called the FPIM coding style.

Why is IM+FPIM considered a better coding style than FMIF? (See this post for the inspiration for this question.)

Here are some criteria which lead me to prefer FMIF over IM:

  1. Shortness of code: It allows me to use shorter function names and thus help stick to the 80 columns-per-line convention.
  2. Readability: chisquare(...) appears more readable than scipy.stats.stats.chisquare(...). Although this is a subjective criterion, I think most people would agree.
  3. Ease of redirection: If I use FMIF and for some reason at some later time want to redirect python to define function from alt_module instead of module I need to change just one line: from alt_module import function. If I were to use IM, I'd need to change many lines of code.
I realize FPIM goes some way to nullifying the first two issues, but what about the third?

I am interested in all reasons why IM+FPIM may be better than FMIF, but in particular, I'd be interested in elaboration on the following points mentioned here:

Pros for IM:

  1. ease of mocking/injecting in tests. (I am not very familiar with mocking, though I recently learned what the term means. Can you show code which demonstrates how IM is better than FMIF here?)
  2. ability for a module to change flexibly by redefining some entries. (I must be misunderstanding something, because this seems to be an advantage of FMIF over IM. See my third reason in favor of FMIF above.)
  3. predictable and controllable behavior on serialization and recovery of your data. (I really don't understand how the choice of IM or FMIF affects this issue. Please elaborate.)
  4. I understand that FMIF "pollutes my namespace", but beyond being a negative-sounding phrase, I don't appreciate how this hurts the code in any concrete way.
PS. While writing this question I received a warning that the question appears subjective and is likely to be closed. Please don't close it. I'm not looking for subjective opinion, but rather concrete coding situations where IM+FPIM is demonstrably better than FMIF.

Many thanks.

5 Answers

Great answers here (I upvoted them all), and here are my thoughts on this matter:

First, addressing each of your bullets:

(Allegedly) Pros of FMIF:

  • Shortness of code: shorter function names help stick to the 80 columns-per-line.

Perhaps, but module names are usually short enough so this is not relevant. Sure, there's datetime, but also os, re, sys, etc. And Python has free line breaks inside { [ (. And for nested modules there's always as in both IM and FPIM

  • Readability: chisquare(...) appears more readable than scipy.stats.stats.chisquare(...).

Strongly disagree. When reading foreign code (or my own code after a few months) it's hard to know where each function comes from. Qualified names saves me from going back and forth from line 2345 to module declarations header. And it also gives you context: "chisquare? What's that? Oh, it's from scypy? Ok, some math-related stuff then". And, once again, you can always abbreviate scipy.stats.stats as scypyst. scypyst.chisquare(...) is short enough with all benefits of a qualified name.

import os.path as osp is another good example, considering it's very common to chain 3 or more of its functions together in a single call: join(expanduser(),basename(splitext())) etc.

  • Ease of redirection: one-line redefinition of a function from altmodule instead of module.

How often you want to redefine a single function but not whole module? Module boundaries and function coordination should be preserved, and Alex already explained this in great depth. For most (all?) real-world scenarios, if alt_module.x is a viable replacement for module.x, then probably alt_module itself is a drop in alternative for module, so both IM and FPIM are one-liners just like FMIF, provided you use as.

  • I realize FPIM goes some way to nullifying the first two issues...

Actually, as is the one that mitigates the first 2 issues (and the 3rd), not FPIM. You can use IM for that too: import some.long.package.path.x as x for the same result as FPIM.


So none of the above are really pros of FMIF. And the reasons I prefer IM/FPIM are:

For the sake of simplicity and consistency, when I import something, either IM or FPIM, I'm always importing a module, not an object from a module. Remember FMIF can be (ab-)used to import functions, classes, variables, or even other modules! Think about the mess of from somemodule import sys, somevar, os, SomeClass, datetime, someFunc.

Also, if you want more than a single object from a module, FMIF will pollute your namespace more than IM or FPIM, which will use a single name no matter how many objects you want to use. And such objects will have a qualified name, which is a pro, not a con: as I've said in issue 2, IMHO a it improves readability.

it all comes down to consistency, simplicity, organization. "Import modules, not objects" is a good, easy mind model to stick with.

I agree with MestreLion the most here (and so an upvote).

My perspective: I review code frequently that I am unfamiliar with, and not knowing what module a function is coming from just looking at the function is quite frustrating.

Code is written once and read many times, and so readability and maintainability trumps ease of typing.

In a similar vein, typically code is not being written for the benefit of the coder, but for the benefit of another entity.

Your code should be readable to someone who knows python better than you, but is unfamiliar with the code.

Full path imports can also better help IDE's point you at the correct source of the function or object you're looking at.

For all of these reasons and the reasons MestreLion noted, I conclude that it is best practice to import and use the full path.

Related