A package is a directory that contains
modules. Having a directory of modules allows us to have modules
contained within other modules. This allows us to use qualified module
names, clarifying the organization of our software.
We can, for example, have several simulations of casino games.
Rather than pile all of our various files into a single, flat directory,
we might have the following kind of directory structure. (This isn't
technically complete, it needs a few additional files.)
casino/
craps/
dice.py
game.py
player.py
roulette/
wheel.py
game.py
player.py
blackjack/
cards.py
game.py
player.py
srategy/
basic.py
martingale.py
bet1326.py
cancellation.py
Given this directory structure, our overall simulation might
include statements like the following.
import craps.game, craps.player
import strategy.basic as betting
class MyPlayer( craps.player.Player ):
def __init__( self, stake, turns ):
betting.initialize(self)
We imported the game
and
player
modules from the
craps
package. We imported the
basic
module from the
strategy
package. We defined a new player based
on a class named Player
in the
craps.player
package.
We have a number of alternative betting strategies, all collected
under the strategy
package. When we import a
particular betting strategy, we name the module
betting
. We can then change to a different
betting strategy by changing the
import
statement.
There are two reasons for using a package of modules.
-
There are a lot of modules, and the package structure
clarifies the relationships among the modules. If we have several
modules related to the game of craps, we might have the urge to
create a craps_game.py module and a craps_player.py module. As soon
as we start structuring the module names to show a relationship, we
can use a package instead.
-
There are alternative implementations, and the package
contains polymorphic modules. In this case, we will often use an
import
package.alternative
as
interface
kind of
import
statement. This is often used for
interfaces and drivers to isolate the interface details and provide
a uniform API to the rest of the Python application.
It is possible to go overboard in package structuring. The general
rule is to keep the package structure relatively flat. Having only one
module at the bottom of deeply-nested packages isn't really very
informative or helpful.