Is 'Import Module' Better Coding Style Than 'From Module Import Function'

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

The negatives you list for IM/FPIM can often be ameliorated by appropriate use of an as clause. from some.package import mymodulewithalongname as mymod can usefully shorten your code and enhance its readability, and if you rename mymodulewithalongname to somethingcompletelydifferent tomorrow, the as clause can be used as a single statement to edit.

Consider your pro-FMIF point 3 (call it R for redirection) vs your pro-FPIM point 2 (call it F for flexibility): R amounts to facilitating the loss of integrity of module boundaries, while F strenghtens it. Multiple functions, classes and variables in a module are often intended to work together: they should not be independently switched to different meanings. For example, consider module random and its functions seed and uniform: if you were to switch the import of just one of them to a different module, then you'd break the normal connection between calls to seed and results of calls to uniform. When a module is well designed, with cohesion and integrity, R's facilitation of breaking down the module's boundaries is actually a negative -- it makes it easier to do something you're better off not doing.

Vice versa, F is what enables coordinated switching of coupled functions, classes, and variables (so, generally, of entities that belong together, by modularity). For example, to make testing repeatable (FPIM pro-point 1), you mock both seed and random in the random module, and if your code follows FPIM, you're all set, coordination guaranteed; but if you have code that has imported the functions directly, you have to hunt down each such module and repeat the mocking over and over and over again. Making tests perfectly repeatable typically also requires "coordinated mocking" of date and time functions -- if you use from datetime import datetime in some modules, you need to find and mock them all (as well as all those doing from time import time, and so forth) to ensure that all the times received when the various parts of the system ask "so what time is it now?" are perfectly consistent (if you use FPIM, you just mock the two relevant modules).

I like FPIM, because there's really not much added value by using a multiply qualified name rather than a singly qualified one (while the difference between barenames and qualified names is huge -- you get so much more control with a qualified name, be it singly or multiply, than you possibly ever can with a barename!).

Ah well, can't devote all of the working day to responding to each and every one of your points -- your question should probably be half a dozen questions;-). I hope this at least addresses "why is F better than R" and some of the mocking/testing issues -- it boils down to preserving and enhancing well-designed modularity (via F) rather than undermining it (via R).

Use 'import module' or 'from module import'?

The difference between import module and from module import foo is mainly subjective. Pick the one you like best and be consistent in your use of it. Here are some points to help you decide.

import module

  • Pros:
    • Less maintenance of your import statements. Don't need to add any additional imports to start using another item from the module
  • Cons:
    • Typing module.foo in your code can be tedious and redundant (tedium can be minimized by using import module as mo then typing mo.foo)

from module import foo

  • Pros:
    • Less typing to use foo
    • More control over which items of a module can be accessed
  • Cons:
    • To use a new item from the module you have to update your import statement
    • You lose context about foo. For example, it's less clear what ceil() does compared to math.ceil()

Either method is acceptable, but don't use from module import *.

For any reasonable large set of code, if you import * you will likely be cementing it into the module, unable to be removed. This is because it is difficult to determine what items used in the code are coming from 'module', making it easy to get to the point where you think you don't use the import any more but it's extremely difficult to be sure.

Is it more efficient to use import module or from module import func?

There is no difference on the import, however there is a small difference on access.

When you access the function as

re.findall() 

python will need to first find the module in the global scope and then find findall in modules dict. May make a difference if you are calling it inside a loop thousands of times.

Importing modules in Python - best practice

import pandas imports the pandas module under the pandas namespace, so you would need to call objects within pandas using pandas.foo.

from pandas import * imports all objects from the pandas module into your current namespace, so you would call objects within pandas using only foo. Keep in mind this could have unexepcted consequences if there are any naming conflicts between your current namespace and the pandas namespace.

from pandas import DataFrame is the same as above, but only imports DataFrame (instead of everything) into your current namespace.

In my opinion the first is generally best practice, as it keeps the different modules nicely compartmentalized in your code.

what is the difference between importing the whole module or importing a certain function?

If you use timeit to test them:

import timeit

print(timeit.Timer('''
from tkinter import ttk
''').timeit())
# 0.47940059999999995

print(timeit.Timer('''
import tkinter
''').timeit())
# 0.09511329999999996

import the full module would be faster than only import specific module.

The memory usage of them(tested by memory_profiler):

from tkinter import ttk

Line # Mem usage Increment Line Contents
================================================
1 18.719 MiB 18.719 MiB @profile
2 def test():
3 21.297 MiB 2.578 MiB from tkinter import ttk
(>2.6)

And:

import tkinter

Line # Mem usage Increment Line Contents
================================================
1 18.676 MiB 18.676 MiB @profile
2 def test():
3 21.070 MiB 2.395 MiB import tkinter
(<=2.5M)

If you only import specific attribute.It would be faster(a little) than import the full module:

import timeit

print(timeit.Timer('''
math.sqrt(4)
''', setup="import math").timeit())
# 0.10590600000000006

print(timeit.Timer('''
sqrt(4)
''', setup="from math import sqrt").timeit())
# 0.08237790000000011

Use from tkinter import ttk just for convenience.if we want to use some sub-attribute, we don't need to type the full module name.You could learn more differences on the question.

PS: I think this overhead is not a big problem.

does import module(or package).function actually import the whole module / package?

Let's say you have the following structure

app/
├── foo/
│ ├── __init__.py
│ ├── foo1.py
│ └── foo2.py
├── bar/
│ ├── __init__.py
│ └── bar1.py
└── app.py

When you say in app.py

import foo

you are saying import all the py files under foo for use in app.py

when you say:

import foo.foo1

you are saying I only want the contents of foo1.py

When you say:

from foo.foo2 import *

you are saying take all the stuff in foo2 and dump it in to the same namespace as app.py.

In scenario 1 you would have to qualify all your calls extremely specifically.

foo.foo1.function()

In scenario 2

foo1.function()

In scenario 3

function()

Ideally you would be using scenario 2 as it is a nice middle ground and helps to prevent namespace pollution.

are there performance advantages to import ... from ...?

The only difference in performance is that one includes an extra attribute lookup:

a = something.method()

while the other references method directly:

a = method()

which is countered by the from ... import ... statement performing the lookup when binding the name. This difference between these actions is negligible.

Importing is really just binding names to already loaded objects. Python loads the whole module the first time if it wasn't yet available, but how you then bind names has no influence over what is loaded.

As such, this is a style choice. People like to be able to determine, at a glance, where an object came from. Importing the module rather than objects from the module gives you this visual reference.



Related Topics



Leave a reply



Submit