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

Let from module import function be called FMIF coding style.

Let import module be called IM coding style.

Let from package import module be called FPIM coding style.

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

Here are some criteria that make me prefer FMIF over IM:

  1. Code brevity: it allows me to use shorter function names and thus help to adhere to 80 column conventions per row.
  2. chisquare(...) : chisquare(...) looks more readable than scipy.stats.stats.chisquare(...) . Although this is a subjective criterion, I think most people will agree.
  3. Ease of redirection: if I use FMIF and for some reason I want to redirect python at some point in order to define function from alt_module instead of module , I only need to change one line: from alt_module import function . If I used IM, I would need to change many lines of code.
I understand that FPIM somehow negates the first two questions, but what about the third?

I am interested in all the reasons why IM + FPIM may be better than FMIF, but in particular, I would be interested to know about the following points mentioned here :

Pros for IM:

  1. ease of ridicule / injection in tests. (I'm not very good at mocking, although I recently learned what the term means. Can you show a code that shows how IM is better than FMIF here?)
  2. the module’s ability to flexibly change by overriding some records. (I have to misunderstand something, because this seems to be an advantage of FMIF compared to IM. See My third reason for FMIF above.)
  3. predictable and manageable behavior when serializing and restoring your data. (I really don’t understand how the choice of IM or FMIF affects this question. Please clarify.)
  4. I understand that FMIF “pollutes my namespace,” but apart from the negative phrase, I don’t understand how it harms the code in any particular way.
PS. When writing this question, I received a warning that the question seems subjective and is likely to be closed. Please do not close it. I'm not looking for a subjective opinion, but rather specific coding situations where IM + FPIM is clearly better than FMIF.

Thank you very much.

+62
python python-import
Nov 16 '09 at 19:18
source share
5 answers

The negatives you list for IM / FPIM can often be improved by using the as clause accordingly. from some.package import mymodulewithalongname as mymod can usefully reduce code and increase its readability, and if you rename mymodulewithalongname to somethingcompletelydifferent tomorrow, the as clause can be used as a single statement for editing.

Read your pro-FMIF point 3 (name it R for redirection) against your pro-FPIM point 2 (name it F for flexibility): R means alleviating the loss of integrity of the module boundaries, while F reinforces it. Several functions, classes, and variables in a module are often designed to work together: they should not be independently switched to different values. For example, consider the random module and its seed and uniform functions: if you were to switch the import of only one of them to another module, then you would break the normal connection between seed calls and the results of uniform calls. When a module is well designed, with cohesion and integrity, R makes it easy to break the boundaries of the module, in fact it is negative - it makes it easier for you to do something that you better not do .

Conversely, F is what allows a coordinated switching of related functions, classes, and variables (generally speaking, entities that belong together in modularity). For example, to make testing repeatable (FPIM pro-point 1), you mock seed and random in the random module, and if your code follows FPIM, you are all set up, coordination is guaranteed; but if you have code that imported functions directly, you need to track down each such module and repeat the mockery again and again. As a rule, tests that repeat perfectly for tests also require a “coordinated mockery” of the date and time functions - if you use from datetime import datetime in some modules, you need to find and mock them (like all those that do from time import time , and so on) to ensure that all the time received when different parts of the system ask, "so what time is it now?" (if you use FPIM, you are simply mocking the two corresponding modules).

I like FPIM because there is really not much added value using a multi-valued name, and not once (while the difference between names and qualified names is huge - you get so ) more control with a qualified name, whether individually or to multiply than you possibly can ever with barename!).

Well, I can’t devote the whole working day to responding to each of your questions - your question should probably be half a dozen questions ;-). I hope this at least concerns “why F is better than R” and some of the taunts / tests - it boils down to maintaining and improving well-designed modularity (via F) rather than undermining it (through R).

+40
Nov 16 '09 at 19:49
source share

The classic text, as often happens, refers to Fredrick Lund, the effect. His advice: always use imports - unless you should.

In other words, be reasonable. Personally, I find that everything that several modules tend to receive is imported through from xyz import a - the main example are Django models. But just like everything else, it is a matter of style, and you should have a consistent one - especially with modules such as datetime , where both the module and the class that it contains are called the same. You need to write datetime.datetime.now() or just datetime.now() ? (In my code, always the first.)

Items 1 and 2 on your question list look the same. The dynamic nature of Python means that it’s quite simple to replace an element in the module namespace no matter which method you use. The difficulty arises if one function in the module refers to another that you want to make fun of. In this case, importing a module, not functions, means that you can do module.function_to_replace = myreplacementfunc , and everything works transparently - but it is as easy to do using FPIM as it is via IM.

I also do not understand how element 3 has anything to do with anything. I think your product 4, however, is based on some misunderstanding. None of the methods you give will “pollute your namespace”. What is it from module import * , where you have no idea what you are importing, and therefore functions can appear in your code without any hints given to the reader where they came from. This is terrible and should be avoided at all costs.

+16
Nov 16 '09 at 19:32
source share

Like Alex Martelli, I like to use as when importing a function.

One thing I did was use some kind of prefix for all functions that were imported from the same module:

 from random import seed as r_seed from random import random as r_random 

r_seed shorter than random.seed , but somewhat preserves the boundaries of the module. Someone accidentally looking at your code may see r_seed() and r_random() and have a chance to understand that they are related.

Of course, you can always just do:

 import random as r 

and then use r.random() and r.seed() , which may be the perfect compromise for this case. I use only the prefix trick when I import one or two functions from a module. When I want to use many functions from the same module, I import the module, possibly with as , to shorten the name.

+5
Nov 16 '09 at 20:16
source share

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

First, referring to each of your bullets:

(Presumably) Pros of FMIF:

  • Code brevity: shorter function names help stick to 80 columns per row.

Perhaps, but the module names are usually quite short, so that doesn't matter. Of course, there is datetime , but also os , re , sys , etc. And Python has free line breaks inside { [ ( . And for nested modules, always as in IM and FPIM

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

I absolutely disagree. When reading external code (or my own code after a few months), it’s hard to know where each function comes from. Qualified names do not allow me to go from line 2345 to the module declaration header. And it also gives you context: " chisquare ? What is it? Oh, is it from scypy ? Well, some math-related stuff then." And again, you can always abbreviate scipy.stats.stats as scypyst . scypyst.chisquare(...) is short enough with all the advantages of a qualified name.

import os.path as osp is another good example, given that it very often combines 3 or more of its functions together in one call: join (expanduser (), basename (splitext ()), etc.

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

How often do you want to override one function, but not the entire module? The boundaries of the modules and the coordination of functions must be preserved, and Alex has already explained this to great depths. For most (all?) Real-world alt_module.x , if alt_module.x is a viable replacement for module.x , then alt_module itself is probably an alternative for module , so both IM and FPIM are single-line like FMIF if you use as .

  • I understand that FPIM somehow negates the first two problems ...

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




Thus, none of the above factors are FMIF pros. And the reasons why I prefer IM / FPIM are as follows:

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

In addition, if you want more than one object from a module, FMIF will pollute your namespace more than IM or FPIM, which will use the same name no matter how many objects you want to use. And such objects will have a qualified name, which is pro, not con: as I said in release 2, IMHO a improves readability.

it all comes down to consistency, simplicity, organization. “Importing Modules, Not Objects” is a good, easy model of the mind.

+5
Nov 07 '13 at 3:26
source share

I agree with MestreLion most of all here (and thus upvote).

My perspective: I often look at code that is unfamiliar to me, and not knowing which module performs the function, just looking at the function is quite difficult.

The code is written once and read many times, and therefore readability and maintainability exceed ease of entry.

In a similar vein, usually the code is not written in favor of the encoder, but in the interests of another entity.

Your code should be readable by someone who knows python better than you, but is not familiar with the code.

Importing the full path may also better help the IDE tell you the correct source of the function or object you are looking at.

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

+1
Nov 10 '13 at 1:56
source share



All Articles