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
- Less maintenance of your
- Cons:
- Typing
module.foo
in your code can be tedious and redundant (tedium can be minimized by usingimport module as mo
then typingmo.foo
)
- Typing
from module import foo
- Pros:
- Less typing to use
foo
- More control over which items of a module can be accessed
- Less typing to use
- 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 whatceil()
does compared tomath.ceil()
- To use a new item from the module you have to update your
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.pyimport foo
you are saying import all the py files under foo for use in app.pywhen you say:
import foo.foo1
you are saying I only want the contents of foo1.pyWhen 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
Method Not Allowed Flask Error 405
Adding a Y-Axis Label to Secondary Y-Axis in Matplotlib
Splitting List Based on Missing Numbers in a Sequence
Changing the Options of a Optionmenu When Clicking a Button
How to Access Class Member Variables in Python
Slicing of a Numpy 2D Array, or How to Extract an Mxm Submatrix from an Nxn Array (N>M)
Pd.Timestamp Versus Np.Datetime64: Are They Interchangeable for Selected Uses
Display Realtime Output of a Subprocess in a Tkinter Widget
Can You Make Multiple "If" Conditions in Python
Increment Numpy Array with Repeated Indices
Multiprocessing:Use Tqdm to Display a Progress Bar
Make Part of a Matplotlib Title Bold and a Different Color
Python Running as Windows Service: Oserror: [Winerror 6] the Handle Is Invalid
Pyspark Dataframes - Way to Enumerate Without Converting to Pandas
Matplotlib: How to Show a Figure That Has Been Closed