levesque levesque - 15 days ago 8
Python Question

Should I use numpy (or pylab) as a python environment by using `from numpy import *`?

I use pylab (more specifically numpy) in all of my python programs­. The exceptions are very rare, if any. So far, I have taken the habit of importing numpy in the following way:

from numpy import *


This has the advantage of making it look like numpy was part of python from the beginning. Is there something bad in the fact of importing numpy like this in every script? I mean apart from the fact that every script/program will require a little bit more memory and will take longer to load.

I think always having to write numpy or even np before every function call that comes from numpy (e.g.,
np.zeros(3)
) is tedious because it requires me to know which function comes from numpy and which doesn't. I don't really care that the zeros function comes from numpy or python, I just want/need to use it.

Which notation is better according to you?

Answer
  1. Using from numpy import * changes the behavior of any, all and sum. For example,

    any([[False]])
    # True
    all([[True, False], [False, False]])
    # True
    sum([[1,2],[3,4]], 1) 
    # TypeError: unsupported operand type(s) for +: 'int' and 'list'
    

    Whereas, if you use from numpy import * then values are completely different:

    from numpy import *
    any([[False]])
    # False
    all([[True, False], [False, False]])
    # False
    sum([[1,2],[3,4]], 1) 
    array([3, 7])
    

    The full set of name collisions can be found this way (thanks to @Joe Kington and @jolvi for pointing this out):

    import numpy as np
    np_locals = set(np.__all__)
    builtins = set(dir(__builtins__))
    print([name for name in np_locals.intersection(builtins) if not name.startswith('__')])
    # ['any', 'all', 'sum']
    
  2. This can lead to very confusing bugs since someone testing or using your code in a Python interpreter without from numpy import * may see completely different behavior than you do.

  3. Using multiple imports of the form from module import * can compound the problem with even more collisions of this sort. If you nip this bad habit in the bud, you'll never have to worry about this (potentially confounding) bug.

    The order of the imports could also matter if both modules redefine the same name.

    And it makes it harding to figure out where functions and values come from.

  4. While it is possible to use from numpy import * and still access Python's builtins, it is awkward:

    from numpy import *
    any([[False]])
    __builtins__.any([[False]])
    

and less readable than:

    import numpy as np
    np.any([[False]])
    any([[False]])
  1. As the Zen of Python says,

    Namespaces are a honking great idea -- let's use more of those!

My advice would be to never use from module import * in any script, period.