The math Module
In addition to the mathematical operators (**, *, /, //, %, +, –) and built-in functions (like abs() and pow()), Python also includes a module called math that contains many other useful functions: To use any of the functions above don’t forget to import the math module and use proper dot notation when calling them! The math module also includes two variables for pi and e. To use these values you must also import the math module and use dot notation:
1 2 3 4 5 |
import math radius = float(input("Enter Radius:")) area = math.pi * radius**2 print ("Area is", round(area,2)) |
Be careful that you don’t change the values of math.pi or math.e in your program. In some languages, like Java and C++, a programmer can define a constant such that any attempt to change its value will cause a syntax error. In Python, while we can “simulate” a constant, and use all uppercase letters to warn programmers that it should not be changed, there is nothing to stop a programmer from actually changing the value if they really want to. Constants in Python are not enforced by the syntax, it’s more of an honour system.
Advanced Importing Techniques
There are actually a few other ways in which you can import modules. Which method you use depends on how you want to access the functions contained in the module. Importing a module this way
import math
creates what is known as a new namespace, which means that you will need to use dot notation to call any of the functions from the module. In my experience, this is the best approach to use because it is the clearest and avoids ambiguous situations. For example, let’s say you import the math module and some module called skyscraper. If the skyscraper module has a function called floor(), which has the same name as the floor() function in the math module, then having to use dot notation makes it very clear what floor() function you want to call.
That said, there are lazier (and riskier) ways to import modules. I’m showing you these techniques because they are (unfortunately) used a lot by professionals and I don’t want you to be confused.
It’s possible to import specific function(s) from a module using the from statement.
from math import floor, pi
Use this method if you just want to import a few things from a module and you know their names won’t conflict with anything else in your program (it takes a lot of experience to know this). In this case, I’ve imported the floor() function and the pi variable. One of the nice things about this is that whatever you import this way becomes part of the current namespace so you no longer need to use dot notation to call them. For example, after the from statement above I can get away with code like this:
print(floor(4.56) * pi)
No “math.” is required, just be sure you don’t have some other function called floor() or variable called pi in your program or another module that you are using.
For the ultimate in laziness, you can use a * symbol to import everything from a module into the current namespace. For example:
from math import *
At least with the previous from statement you know exactly what is being imported into the current namespace. Using the * saves typing but it’s generally considered poor style because it’s not clear what your program really needs from the module, or where potential naming conflicts might occur.
Again, I’m only showing you the from statement because you may see it in the future, for now, please use the standard form of the import statement and dot notation for maximum clarity.
Style Rule #9: Importing ModulesAlways use the standard form of the import statement when importing modules, and dot notation when calling imported functions. This makes it clear exactly which module a function is being called from and avoids naming conflicts. Avoid using the from statement! |
Creating Your Own Modules
As your programs become larger and more complex, the need to organize your code becomes greater. You have already learned that a large and complex program should be divided into functions that each perform a specific task. As you write more and more functions in a program, you should consider organizing the functions by storing them in modules. The computer science term for this is modularization.
Recall that a module is simply a (.py) file that contains a collection of Python functions that perform related tasks. Modules make it easier to reuse functions in more than one program. If you think about the math module again, it contains a collection of related and commonly useful math functions. Thousands of Python programmers around the world regularly import this module and benefit from those functions without having to reinvent the wheel.
Let’s say we need to write a program that can calculate the area and circumference of a circle and the area and perimeter of a rectangle. There are obviously two categories of calculations required: those for circles, and those for rectangles. Here is what the circle(.py) module might look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
"""Author: Vik Twenty Date: November 23, 2021 Description: The circle module has functions that perform calculations related to circles. """ import math def area(radius): """This function accepts a circle's radius as an argument and returns the area of the circle.""" return math.pi * radius**2 def circumference(radius): """This function accepts a circle's radius as an argument and returns the circle's circumference.""" return 2 * math.pi * radius |
And, here is the rectangle(.py) module:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
"""Author: Vik Twenty Date: November 23, 2021 Description: The circle module has functions that perform calculations related to rectangles. """ def area(width, length): """This function accepts a rectangle's width and length as arguments and returns the area of the rectangle.""" return width * length def perimeter(width, length): """This function accepts a rectangle's width and length as arguments and returns the perimeter of the rectangle.""" return 2 * (width + length) |
Notice that both of these modules contain function definitions but no code to call the functions. As with variable and function names, be sure that you don’t use a Python keyword to name your module. Also, all module files must end with the .py extension.
To access the functions in our circle and rectangle modules, we need to import them into our main program, then we can call the functions using dot notation as usual.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
"""Author: Vik Twenty Date: November 23, 2021 Description: This program allows the user to choose various geometry calculations from a menu. It imports the circle and rectangle modules. """ import circle import rectangle # The main function. def main(): # The choice variable controls the loop # and holds the user's menu choice. choice = 0 while choice != 5: # display the menu. display_menu() # Get the user's choice. choice = int(input('Enter your choice: ')) # Perform the selected action. if choice == 1: radius = float(input("Enter the circle's radius: ")) print('The area is', circle.area(radius) ) elif choice == 2: radius = float(input("Enter the circle's radius: ")) print('The circumference is', \ circle.circumference(radius)) elif choice == 3: width = float(input("Enter the rectangle's width: ")) length = float(input("Enter the rectangle's length: ")) print('The area is', rectangle.area(width, length)) elif choice == 4: width = float(input("Enter the rectangle's width: ")) length = float(input("Enter the rectangle's length: ")) print('The perimeter is', \ rectangle.perimeter(width, length)) elif choice == 5: print('Exiting the program...') else: print('Error: invalid selection.') def display_menu(): """This function simply displays a menu. It takes no parameters and returns nothing.""" print(' MENU') print('1) Area of a circle') print('2) Circumference of a circle') print('3) Area of a rectangle') print('4) Perimeter of a rectangle') print('5) Quit') # Call the main function. main() |
The example above is a menu-driven program. A menu-driven program displays a list of options and allows the user to select the one that they want to perform. Also notice that the if..elif..else statement provides basic input validation to ensure that the user selects a valid menu option.
Another Benefit of Docstrings
I hope you noticed the exemplary use of docstrings in the header comment of each module and for each function I defined, and I’m sure by now you appreciate how important internal documentation like this is for others reading your program. But there’s another big benefit!
Try this in the Python shell. Import the circle module we just created.
>>> import circle
You already know that we can get a list of functions by using the dir() built-in function like this:
>>> dir(circle)
[‘__builtins__’, ‘__doc__’, ‘__file__’, ‘__name__’, ‘area’, ‘circumference’, ‘math’]
You can see the area(), circumference(), and math() functions at the end of the list. Now, watch what happens if we use the built-in help() function:
Sick Yo! The Python interpreter reads all of the docstrings in the circle module code that it normally ignores when running your program and automatically generates beautifully formatted documentation for the module. For professional programmers, this is a huge productivity booster because they only need to document their code once, and can use that to automatically create additional external documentation. Java has something similar (but even more powerful) called JavaDocs that we’ll learn about in ICS4U.
You Try!
-
- Start a new page in your Learning Journal titled “2-8 Modules“. Carefully read the notes above and in your own words summarize the key ideas from each section.
- Write a program that asks the user to enter the x and y coordinates for two points. Calculate and display the distance between the two points, and the slope of the line. Use the sqrt() and pow() functions from the math module.
- Create a module named grading that contains the following two functions:
- calcAverage() – this function should accept five (integer) test scores as arguments and return the average (float) of the scores.
- determineGrade() – this function should accept a test score as an argument and return a letter grade (string) for the score, based on the following:
Write a program that imports your grading module. Your program should include a main() function that asks the user to enter five (integer) test scores. The program should display a letter grade for each score and the average test score rounded to 1 decimal place.
- For an even greater challenge, modify your determineGrade() function to include a + or – after the letter grade based on the last digit of the mark. Examples: 80% = B-, 65% = D, 98% = A+. Hint: The % operator can be used to get the first digit of an integer.