1

Say I have a script called src.py with several functions defined in it; the functions are all in a class called LDA. These functions need libraries such as numpy, scipy and others, which are imported as standard at the top of the script.

Now in a new separate script, called main.py, I import the class LDA:

from src import LDA

If I now use the LDA class and all its functions in the new main.py script, the functions all work correctly, even though I did not import the dependencies needed in src.py. How does this work? Shouldn't I need to import numpy, scipy and so on in main.py for LDA to work?

PyRsquared
  • 6,970
  • 11
  • 50
  • 86

1 Answers1

4

This and similar questions have already been answered here. See this and also this to understand the significance of python import module and from module import class features.

In summary both import X and from X import class executes the target file line by line so all the dependencies will automatically be loaded in the module's namespace. So if you instantiate the class and run the functions/methods they will be looked up in the namespace (a fancy dictionary) of X where references to the dependencies are present. The from X import class creates a reference to class with the same name after importing so it can be used without qualification. But the caveat is the module X has no reference so the objects cannot be accessed with X.obj qualifier. With an ordinary import X statement you can access all the objects defined in X.

Side Note: The dir() function and dict attribute of an imported object is a great way to see what objects are loaded. An example is given below

#script test.py
import numpy as np

class Baz():
    def __init__(self, num):
        self.a = np.arange(num)
        self.b = np.ones(num)
        print self.a, self.b

    def foo(self):
        prod = np.dot(self.a, self.b)
        return prod

>>> import test
>>> dir(test)
['Baz', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'np']
>>> test.__dict__.keys()
['__builtins__', '__file__', 'Baz', '__package__', 'np', '__name__', '__doc__']
>>> test.__dict__['np']
<module 'numpy' from '/home/user/bin/python2.7/site-packages/numpy/__init__.pyc'>
>>> x = test.Baz(5)
[0 1 2 3 4] [ 1.  1.  1.  1.  1.]
>>> x.foo()
10.0

Now the from import statement

>>> from test import Baz
>>> dir(test)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'test' is not defined
>>> dir(Baz)
['__doc__', '__init__', '__module__', 'foo']
>>> Baz.__module__
'test'
>>> Baz.__dict__.keys()
['__module__', 'foo', '__doc__', '__init__']
>>> x = Baz(5)
[0 1 2 3 4] [ 1.  1.  1.  1.  1.]
>>> x.foo()
10.0
>>> Baz.__dict__['foo'].__globals__.keys()
['__builtins__', '__file__', 'Baz', '__package__', 'np', '__name__', '__doc__']

As you can see the module numpy is loaded and available in the __globals__ attribute of the function which again returns the dictionary of all loaded modules. So when the foo() method is run it performs a lookup in the namespace dictionary and locates numpy.

SigmaPiEpsilon
  • 678
  • 5
  • 15