"from module import data; print(data)" vs "import module; print(module.data)"

Steven D'Aprano steve+comp.lang.python at pearwood.info
Wed Feb 24 22:39:12 EST 2016


On Thursday 25 February 2016 12:07, Dan Stromberg wrote:

> Could people please compare and contrast the two ways of doing imports
> in the Subject line?

from module import data; print(data)

import module; print(module.data)


> I've long favored the latter, but I'm working in a code base that
> prefers the former.
> 
> Is it fair to say that the former increases the surface area of your
> shared (sometimes mutable) state?

No, I can't say that it is. If anything, the opposite is the case: it 
decreases the surface area, because `data` now is local to the importing 
(not imported) module. Rebinding data will not affect anything else.


There are two scenarios (`from module import...` versus `import ...`), each 
with two cases: mutation, and rebinding:

(1) from module import data

(a) Mutation (only applies to mutable data like lists, dicts etc)

In place mutation affects everything relying on module.data regardless of 
how or where it is accessed.

(b) Rebinding (e.g. `data = []`)

Because data is now a local name, you only affect the local scope.

(2) import module

(a) Mutation is no different from (1)(a) above. No change.

(b) Rebinding `module.data = []` affects the imported module, and therefore 
everything that relies on it.

So the `from module import data` scenario reduces the number of ways that 
you can affect other modules. That may be important to you, but usually the 
answer to that is "well don't rebind attributes of modules unless you really 
mean to". Sometimes doing `module.data = ...` is not a bad thing.

On the other hand, seeing something like:

    module.data.append(999)

should stand out to a reasonably experienced developer as possibly effecting 
other modules. But:

    data.append(999)

may fool them into thinking that the change is only local to the current 
module. Dangerous things should look dangerous: this is a point in favour of 
using `import module` in preference to `from`.


> It's clear that the former saves keystrokes.

Code is read about 100 times more than it is written. Saving keystokes 
should be quite low on the list of priorities.

It also saves line width, which may sometimes impact readability. But then 
readability is only weakly correlated to line length. As you say:

> I find the latter a little more clear, because you don't have to go
> look for where a symbol came from.

which is also a very good point.

Personally, I prefer the `import module` over `from module` except when I 
don't. Consequently I will sometimes even use both in the same module:


import os
from itertools import zip_longest


depending on what's more convenient and useful for each.

I think that having a hard rule that you MUST use one or the other is silly, 
but I guess that since Python makes "brace wars" irrelevant people need to 
find something else to argue about.

http://encyclopedia2.thefreedictionary.com/1+true+brace+style


> PS: Haskell seems better at the former than Python; Haskell tells you
> if you import two identical symbols from two different places, when
> you try to use one of them - not at import time.  I believe in Python,
> whichever symbol you import last, wins.  Haskell does not warn you at
> import time, which is fine.  Not sure about OCaml or whatever else.

Haskell assumes that importing the same style from two places is an error 
that needs warning about. I don't think it is, any more than:

s = 'foo'
s = 'bar'

is necessarily an error (particular if the two rebindings are separated by 
code that does things). Both `import` and `from ... import` are rebinding 
operations, like = assignment.


-- 
Steve




More information about the Python-list mailing list