So far we have been working with fairly short, simple programs contained in single files. That style works great for scripts; but most real applications are more complex, and thus better split among several files.
Consider the file layout of a sample program:
foobar/ __init__.py foo.py bar/ __init__.py baz.py
Python considers any folder that is on the
PYTHONPATH and contains an
__init__.py file to be a package, and thus importable.
__init__.py file’s primary purpose is to be a marker - any folder
__init__.py file is an importable package. The file likewise
defines the top level of said package’s namespace.
Almost every Python package contains an
__init__.py file; and the file
name tells us nothing about the contents of the file, except that it is
package marker. Therefore it is considered inappropriate to put real
functionality - class definitions, functions, etc - into an
It is commonplace for
__init__.py to be left completely empty. If it does
contain code, it will typically be limited to docstrings, version constants, and
import statements. Since the
__init__.py file is the top level of it’s
package’s namespace, by importing an object into
__init__.py we promote that
into the module’s top level namespace.
Consider what an
__init__.py file from the example program above might look
''' Foobar A program that puts the foo into bar! (Caution, use at your own risk. Your mileage may vary.) ''' VERSION = '0.1' from foo import Spam from bar.baz import Eggs
In this example, two classes will be available in the top level namespace of the
Spam, which is defined in
Eggs which is
foobar/bar/baz.py. Both classes were imported above into
__init__.py. Consequently code outside this package can import those classes
from foobar import VERSION from foobar import Spam from foobar import Eggs # Not imported in __init__.py, so we have to use the full path: from foobar.bar.baz import Ham
Note that in Python, unlike in Java, it is commonplace for multiple class definitions to live in one file. Nor is there necessarily any relationship between the name of a file and the name(s) of the object(s) it contains.