1.4. Sharing and Reusing Code with Modules

1.4.1. Modules and Getting Help

A module is a file containing Python definitions and statements intended for use in other Python programs. There are many Python modules that come with Python as part of the standard library.

The Python Documentation site for Python version 3 (the home page is shown below) is an extremely useful reference for all aspects of Python. The site contains a listing of all the standard modules that are available with Python (see Global Module Index). You will also see that there is a Language Reference and a Tutorial, as well as installation instructions, how-tos, and frequently asked questions. We encourage you to become familiar with this site and to use it often.

../_images/pythondocmedium.png

If you have not done so already, take a look at the Global Module Index. Here you will see an alphabetical listing of all the modules that are available as part of the standard library.

Note: Python modules and limitations with activecode

Throughout the chapters of this book, activecode windows allow you to practice the Python that you are learning. We mentioned in the first chapter that programming is normally done using some type of development environment and that the activecode used here was strictly to help us learn. It is not the way we write production programs.

To that end, it is necessary to mention that many of the modules available in standard Python will not work in the activecode environment. In fact, only turtle, math, and random have been ported at this point. If you wish to explore any additional modules, you will need to also explore using a more robust development environment.

Check your understanding

    data-2-15: In Python a module is:
  • (A) A file containing Python definitions and statements intended for use in other Python programs.
  • A module can be reused in different programs.
  • (B) A separate block of code within a program.
  • While a module is separate block of code, it is separate from a program.
  • (C) One line of code in a program.
  • The call to a feature within a module may be one line of code, but modules are usually multiple lines of code separate from the program
  • (D) A file that contains documentation about functions in Python.
  • Each module has its own documentation, but the module itself is more than just documentation.
    data-2-16: To find out information on the standard modules available with Python you should:
  • (A) Go to the Python Documentation site.
  • The site contains a listing of all the standard modules that are available with Python.
  • (B) Look at the import statements of the program you are working with or writing.
  • The import statements only tell you what modules are currently being used in the program, not how to use them or what they contain.
  • (C) Ask the professor
  • While the professor knows a subset of the modules available in Python, chances are the professor will have to look up the available modules just like you would.
  • (D) Look in this textbook.
  • This book only explains a portion of the modules available. For a full listing you should look elsewhere.
    data-2-17: True / False: All standard Python modules will work in activecode.
  • (A) True
  • Only turtle, math, and random have been ported to work in activecode at this time.
  • (B) False
  • Only turtle, math, and random have been ported to work in activecode at this time.

1.4.2. The math module

The math module contains the kinds of mathematical functions you would typically find on your calculator and some mathematical constants like pi and e. As we noted above, when we import math, we create a reference to a module object that contains these elements.

../_images/mathmod.png

Here are some items from the math module in action. If you want more information, you can check out the Math Module Python Documentation.

Mathematical functions do not need to be constructed. They simply perform a task. They are all housed together in a module called math. Once we have imported the math module, anything defined there can be used in our program. Notice that we always use the name of the module followed by a dot followed by the specific item from the module (math.sqrt). You can think of this as lastname.firstname where the lastname is the module family and the firstname is the individual entry in the module.

If you have not done so already, take a look at the documentation for the math module.

Check your understanding

    data-2-18: Which statement allows you to use the math module in your program?
  • (A) import math
  • The module must be imported before you can use anything declared inside the module.
  • (B) include math
  • The correct term is not include, but you are close.
  • (C) use math
  • You will be using parts of the module, but that is not the right term.
  • (D) You don't need a statement. You can always use the math module
  • You cannot use a Python module without a statement at the top of your program that explicitly tells Python you want to use the module.

1.4.3. The import statement

There are three ways to import a module. The first is the basic import statement, as shown below.

In [1]: import math

When using this import statement, all the objects from the math module live in the math namespace and are accessed using the . notation. For example, to see an approximation of \(\pi\), we would use math.pi.

In [1]: math.pi

It can be inconvenient to type the module name before each object and there are two ways to avoid this annoyance. First, we could assign a short alias for the module using the import-as statement.

In [1]: import math as m

In [1]: m.cos(m.pi/2)

The other alternative is to import elements into the main namespace using the from-import statement, as shown below. In this case, we no longer need to use the module name and dot notation to access the objects.

In [1]: from math import pi, cos

In [1]: cos(pi/2)

You may be wondering why anyone might use the import or import-as statements and subject themselves to the inconvenience of prepending all module objects with the dot notation. The primary advantage to using these forms of the import statement is that they avoid naming conflicts. For example, both the math standard library and the numpy numerical library have a cosine function. In the example shown below, the second import statement shadows the first cos function from the math module, which usually leads to a bug.

In [1]: from math import pi, cos

In [1]: from numpy import cos

In [1]: cos(pi/2)

In this case, we were lucky that both cos functions worked the same way. The numpy cos function has the added functionality of working on lists. Let’s change the example to introduce a bug.

In [1]: from numpy import cos

In [1]: from math import pi, cos

In [1]: xs = [1,2,3]

In [1]: cos(xs)

In this last example, the math cos function “overwrites” the numpy cos because math is imported second. When trying to apply the cos to a list, we get an error as the math cos doesn’t work on a list, only numbers. We can avoid this shadowing using an alias for the modules.

In [1]: import numpy as np

In [1]: import math as m

In [1]: xs = [1,2,3]

In [1]: np.cos(xs)

1.4.4. The random module

We often want to use random numbers in programs. Here are a few typical uses:

  • To play a game of chance where the computer needs to throw some dice, pick a number, or flip a coin,
  • To shuffle a deck of playing cards randomly,
  • To randomly allow a new enemy spaceship to appear and shoot at you,
  • To simulate possible rainfall when we make a computerized model for estimating the environmental impact of building a dam,
  • For encrypting your banking session on the Internet.

Python provides a module random that helps with tasks like this. You can take a look at it in the documentation. Here are the key things we can do with it.

Press the run button a number of times. Note that the values change each time. These are random numbers.

The randrange function generates an integer between its lower and upper argument, using the same semantics as range — so the lower bound is included, but the upper bound is excluded. All the values have an equal probability of occurring (i.e. the results are uniformly distributed).

The random() function returns a floating point number in the range [0.0, 1.0) — the square bracket means “closed interval on the left” and the round parenthesis means “open interval on the right”. In other words, 0.0 is possible, but all returned numbers will be strictly less than 1.0. It is usual to scale the results after calling this method, to get them into a range suitable for your application.

In the case shown here, we’ve converted the result of the method call to a number in the range [0.0, 5.0). Once more, these are uniformly distributed numbers — numbers close to 0 are just as likely to occur as numbers close to 0.5, or numbers close to 1.0. If you continue to press the run button you will see random values between 0.0 and up to but not including 5.0.

It is important to note that random number generators are based on a deterministic algorithm — repeatable and predictable. So they’re called pseudo-random generators — they are not genuinely random. They start with a seed value. Each time you ask for another random number, you’ll get one based on the current seed attribute, and the state of the seed (which is one of the attributes of the generator) will be updated. The good news is that each time you run your program, the seed value is likely to be different meaning that even though the random numbers are being created algorithmically, you will likely get random behavior each time you execute.

Lab

  • Sine Wave In this guided lab exercise we will have the turtle plot a sine wave.

Check your understanding

    data-2-19: Which of the following is the correct way to reference the value pi within the math module. Assume you have already imported the math module.
  • (A) math.pi
  • To invoke or reference something contained in a module you use the dot (.) notation.
  • (B) math(pi)
  • This is the syntax for calling a function, not referencing an item in a module.
  • (C) pi.math
  • The module name must come first when accessing values and functions with a module.
  • (D) math->pi
  • The -> notation is not used in Python.
    data-2-20: Which module would you most likely use if you were writing a function to simulate rolling dice?
  • (A) the math module
  • While you might want to use the math module for other numerical computations in your program, it does not contain functions that are likely to help you simulate a dice roll.
  • (B) the random module
  • You would likely call the function random.randrange.
  • (C) the turtle module
  • The turtle module, while producing interesting graphics, is unlikely to help you here.
  • (D) the game module
  • Python does not have a game module.
    data-2-21: The correct code to generate a random number between 1 and 100 (inclusive) is:
  • (A) prob = random.randrange(1, 101)
  • This will generate a number between 1 and 101, but does not include 101.
  • (B) prob = random.randrange(1, 100)
  • This will generate a number between 1 and 100, but does not include 100. The highest value generated will be 99.
  • (C) prob = random.randrange(0, 101)
  • This will generate a number between 0 and 100. The lowest value generated is 0. The highest value generated will be 100.
  • (D) prob = random.randrange(0, 100)
  • This will generate a number between 0 and 100, but does not include 100. The lowest value generated is 0 and the highest value generated will be 99.
    data-2-22: One reason that lotteries don’t use computers to generate random numbers is:
  • (A) There is no computer on the stage for the drawing.
  • They could easily put one there.
  • (B) Because computers don't really generate random numbers, they generate pseudo-random numbers.
  • Computers generate random numbers using a deterministic algorithm. This means that if anyone ever found out the algorithm they could accurately predict the next value to be generated and would always win the lottery.
  • (C) They would just generate the same numbers over and over again.
  • This might happen if the same seed value was used over and over again, but they could make sure this was not the case.
  • (D) The computer can't tell what values were already selected, so it might generate all 5's instead of 5 unique numbers.
  • While a programmer would need to ensure the computer did not select the same number more than once, it is easy to ensure this.

Note

This workspace is provided for your convenience. You can use this activecode window to try out anything you like.

1.4.5. Making your own modules

Making your own modules is as easy as saving the functions and values in a file with the .py extension. Provided that Python can find your file, you will now be able to import and use your code in other programs.

Note

The easiest way to make sure that Python can locate your module is keeping in in the current working directory. In IPython, you can see the location of the current working directory using the pwd magic alias.

In [1]: pwd

Other methods for providing access to your module includes adding the modules address to the PYTHONPATH or using the distutils standard module to provide an installation of your module. The best way to share a module in Python is using the Python Package Index, which allows users to install your program using pip. For more information, take a look at this tutorial.

Next Section - 1.5. Python as an Object Oriented Language