# 5. Python Modules ## 5.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**. We have already used one of these quite extensively, the `turtle` module. Recall that once we import the module, we can use things that are defined inside. ```python import turtle # allows us to use the turtles library wn = turtle.Screen() # creates a graphics window alex = turtle.Turtle() # create a turtle named alex alex.forward(150) # tell alex to move forward by 150 units alex.left(90) # turn by 90 degrees alex.forward(75) # complete the second side of a rectangle wn.exitonclick() ``` Here we are using `Screen` and `Turtle`, both of which are defined inside the turtle module. But what if no one had told us about turtle? How would we know that it exists. How would we know what it can do for us? The answer is to ask for help and the best place to get help about the Python programming environment is to consult with the Python Documentation. The [Python Documentation](http://docs.python.org/py3k/) 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](http://docs.python.org/py3k/py-modindex.html)). You will also see that there is a [Language Reference](http://docs.python.org/py3k/reference/index.html) and a [Tutorial](http://docs.python.org/py3k/tutorial/index.html) (mostly aimed at people who are already familiar with another programming language), 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.  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. Find the turtle module.   You can see that all the turtle functionality that we have talked about is there. However, there is so much more. Take some time to read through and familiarize yourself with some of the other things that turtles can do. 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 completely 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** In Python a module is: * A file containing Python definitions and statements intended for use in other Python programs. * A module can be reused in different programs. * A separate block of code within a program. * While a module is separate block of code, it is separate from a program. * 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 * A file that contains documentation about functions in Python. * Each module has its own documentation, but the module itself is more than just documentation. To find out information on the standard modules available with Python you should: * Go to the Python Documentation site. * The site contains a listing of all the standard modules that are available with Python. * 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. * 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. * Look in this textbook. * This book only explains a portion of the modules available. For a full listing you should look elsewhere. True / False: All standard Python modules will work in activecode. * True * Only turtle, math, and random have been ported to work in activecode at this time. * False * Only turtle, math, and random have been ported to work in activecode at this time. ## 5.2. More About Using Modules Before we move on to exploring other modules, we should say a bit more about what modules are and how we typically use them. One of the most important things to realize about modules is the fact that they are data objects, just like any other data in Python. Module objects simply contain other Python elements. The first thing we need to do when we wish to use a module is perform an `import`. In the example above, the statement `import turtle` creates a new name, `turtle`, and makes it refer to a module object. This looks very much like the reference diagrams we saw earlier for simple variables.  In order to use something contained in a module, we use the dot notation, providing the module name and the specific item joined together with a “dot”. For example, to use the `Turtle` class, we say `turtle.Turtle`. You should read this as: “In the module turtle, access the Python element called Turtle”. We will now turn our attention to a few other modules that you might find useful. ## 5.3. 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.  Here are some items from the math module in action. If you want more information, you can check out the [Math Module](http://docs.python.org/py3k/library/math.html#module-math) Python Documentation. ```python import math print(math.pi) print(math.e) print(math.sqrt(2.0)) print(math.sin(math.radians(90))) # sin of 90 degrees ``` Notice another difference between this module and our use of `turtle`. In `turtle` we create objects (either `Turtle` or `Screen`) and call methods on those objects. Remember that a turtle is a data object (recall `alex` and `tess`). We need to create one in order to use it. When we say `alex = turtle.Turtle()`, we are calling the constructor for the Turtle class which returns a single turtle object. 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** Which statement allows you to use the math module in your program? * import math * The module must be imported before you can use anything declared inside the module. * include math * The correct term is not include, but you are close. * use math * You will be using parts of the module, but that is not the right term. * 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. ## 5.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. ```python import random prob = random.random() print(prob) diceThrow = random.randrange(1, 7) # return an int, one of 1,2,3,4,5,6 print(diceThrow) ``` 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. ```python import random prob = random.random() result = prob * 5 print(result) ``` 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](../Labs/sinlab.html) In this guided lab exercise we will have the turtle plot a sine wave. **Check your understanding** 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. * math.pi * To invoke or reference something contained in a module you use the dot (.) notation. * math(pi) * This is the syntax for calling a function, not referencing an item in a module. * pi.math * The module name must come first when accessing values and functions with a module. * math->pi * The -> notation is not used in Python. Which module would you most likely use if you were writing a function to simulate rolling dice? * 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. * the random module * You would likely call the function random.randrange. * the turtle module * The turtle module, while producing interesting graphics, is unlikely to help you here. * the game module * Python does not have a game module. The correct code to generate a random number between 1 and 100 (inclusive) is: * prob = random.randrange(1, 101) * This will generate a number between 1 and 101, but does not include 101. * 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. * 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. * 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. One reason that lotteries don’t use computers to generate random numbers is: * There is no computer on the stage for the drawing. * They could easily put one there. * 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. * 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. * 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. ## 5.5. Creating Modules You’ve seen how to *use* modules like `random`, `math`, and `turtle`, but how would you *create* a module? Every time you’ve written a Python script you’ve created a module! A Python module is just a Python source code file. Let’s consider the Python file shown below. *coffee\_shop.py* ```python """ The coffee shop module contains functions and contains variables important to implementing a coffee shop. """ # Set some variables shop_name = "Runestone Brew House" coffee_sizes = ["small", "medium", "large"] coffee_roasts = ["hot chocolate", "light", "medium", "dark", "espresso"] ``` This is a Python script named `coffee_shop.py` that contains three variables: `shop_name`, `coffee_sizes`, and `coffee_roasts`. The `shop_name` is a string, `coffee_sizes` is a list containing strings, and `coffee_roasts` is also a list containing strings. A module is another name for: * the code inside a function * The code inside a function is called a function body. * a file containing Python code * Python modules are just Python source code files. * the comments before a function * The comments just before a function are the function documentation. * a small block of Python code * Modules may be small, but there is a more accurate answer. That’s so great! We’ve got the basics of a coffee shop. All you need is some roasted coffee and cups. You’re good to go. If you try to run that code though, it doesn’t do much that’s visible to a user… How can we use the `coffee_shop` module? We can import it and use it in other Python source code files. Let’s consider the Python file shown below. *coffee\_customer.py* ```python import coffee_shop # Output the information we know from the module print("Welcome to", coffee_shop.shop_name) print("Available sizes:", coffee_shop.coffee_sizes) print("Available roasts:", coffee_shop.coffee_roasts) ``` This is a Python script named `coffee_customer.py` that imports our `coffee_shop` module, then prints out the information from that module. Note The module files must be in the same directory on your computer for Python to know how to import them automatically Create a module by: * writing a new function or class * You may write a function or class inside a module, but this alone does not create one. * placing an import statement at the top of a file * Import statements permit you to use other modules, but they do not create one. * placing code in a Python file in the same directory as your other source code * Modules are Python source code files. * creating a comment block at the beginning of a file * Modules should include comment blocks at the top, but writing a comment block at the top of a file does not create a new module. We use **dot notation** to grab the `shop_name`, `coffee_sizes`, and `coffee_roasts` variables from the `coffee_shop` module. Then we print them out as parts of nice messages. Variables aren’t the only thing we can place in modules though… We can put any valid Python code in them. Let’s improve our coffee shop! *coffee\_shop.py* ```python """ The coffee shop module contains functions and contains variables important to implementing a coffee shop. """ # Set some variables shop_name = "Runestone Brew House" coffee_sizes = ["small", "medium", "large"] coffee_roasts = ["hot chocolate", "light", "medium", "dark", "espresso"] def order_coffee(size, roast): """ Take an order from a user :param size: a string containing one of the coffee_sizes :param roast: a string containing one of the coffee_roasts :return: a message about the coffee order """ return "Here's your {} coffee roasted {}".format(size, roast) ``` The old file contents are present, but now there’s also an `order_coffee` function that takes two arguments, `size` and `roast`. Also - look at all the awesome comments in there! Module Comments It is important to include header comments in your module that explain what the module does. Function Comments Functions are the next chapter, but the comments used here demonstrate a common Python documentation style. Ok - so we’ve got a function in our module now, let’s use it. *coffee\_customer.py* ```python # Import the module with coffee_shop functionality import coffee_shop # Output the information we know from the module print("Welcome to", coffee_shop.shop_name) print("Available sizes:", coffee_shop.coffee_sizes) print("Available roasts:", coffee_shop.coffee_roasts) # Get some inputs from the user order_size = input("What size coffee do you want? ") order_roast = input("What roast do you want? ") # Send the order to the coffee shop module shop_says = coffee_shop.order_coffee(order_size, order_roast) # Print out whatever it gave back to us print(shop_says) ``` What determines the name of our import? * the first variable name in the module * This does not determine module name, and not all modules export variables. * a comment early in the module * This does not determine module name, and comments are not mandatory components of modules. * it's called whatever we name it in the "import" statement * The import statement uses the module name to lookup the correct module, and an import statement is not used to create the module. * the filename of the module * The filename of the module determines the name of the import. We added some lines to our `coffee_customer` script… Now after printing data nicely, `coffee_customer` asks the user for a size and a roast. These are the parameters required by our `order_coffee` function over in the `coffee_shop` module! Call the `order_coffee` function with **dot notation**, just like retrieving variable values. The function call is the line that says `shop_says = coffee_shop.order_coffee(order_size, order_roast)`. The function returns something, so we save that off in `shop_says`. The next line prints out whatever the shop said. Coffee shops do more than just coffee! Maybe you want some milk. We need to add some functionality to our coffee shop. Check it out below. *coffee\_shop.py* ```python """ The coffee shop module contains functions and contains variables important to implementing a coffee shop. """ # Set some variables shop_name = "Runestone Brew House" coffee_sizes = ["small", "medium", "large"] coffee_roasts = ["hot chocolate", "light", "medium", "dark", "espresso"] def order_coffee(size, roast): """ Take an order from a user :param size: a string containing one of the coffee_sizes :param roast: a string containing one of the coffee_roasts :return: a message about the coffee order """ return "Here's your {} coffee roasted {}".format(size, roast) def add_milk_please(fat_content): """ Pretend like we're adding some milk to a coffee :param fat_content: a string or integer containing the milkfat content :return: a message about having added the milk """ return "I've added the {}% milk".format(fat_content) ``` The new function is called `add_milk_please` and it takes one parameter - the `fat_content`. It returns a string explaining what happened. This is great. But the function isn’t going to do anything by itself. We have to call it. Check out the update to our `coffee_customer` script below. *coffee\_customer.py* ```python # Import the module with coffee_shop functionality import coffee_shop # Output the information we know from the module print("Welcome to", coffee_shop.shop_name) print("Available sizes:", coffee_shop.coffee_sizes) print("Available roasts:", coffee_shop.coffee_roasts) # Get some inputs from the user order_size = input("What size coffee do you want? ") order_roast = input("What roast do you want? ") # Send the order to the coffee shop module shop_says = coffee_shop.order_coffee(order_size, order_roast) # Print out whatever it gave back to us print(shop_says) # See if the user wants to add milk add_milk_response = input("Do you want to add milk (y/n)? ") # Convert the response to lowercase, then check for a "yes" answer if "y" in add_milk_response.lower(): milk_fat = input("What percent milk do you want added? ") shop_says = coffee_shop.add_milk_please(milk_fat) # Print out whatever it gave back to us print(shop_says) ``` That got fancy! We were just ordering coffee but now the user can choose to add milk! Selection is in a couple chapters, but if you read that code like english you’ll see what’s going on. The call to `add_milk_please` happens right in there - it looks just like the other one: `shop_says = coffee_shop.add_milk_please(milk_fat)`. Let’s wrap this coffee shop visit up. But - you better leave a tip. We’ll add another function to our coffee shop to enable that. *coffee\_shop.py* ```python """ The coffee shop module contains functions and contains variables important to implementing a coffee shop. """ # Set some variables shop_name = "Runestone Brew House" coffee_sizes = ["small", "medium", "large"] coffee_roasts = ["hot chocolate", "light", "medium", "dark", "espresso"] def order_coffee(size, roast): """ Take an order from a user :param size: a string containing one of the coffee_sizes :param roast: a string containing one of the coffee_roasts :return: a message about the coffee order """ return "Here's your {} coffee roasted {}".format(size, roast) def add_milk_please(fat_content): """ Pretend like we're adding some milk to a coffee :param fat_content: a string or integer containing the milkfat content :return: a message about having added the milk """ return "I've added the {}% milk".format(fat_content) def give_tip(tip_amount): """ Take a tip from the user, then be happy about it :param tip_amount: the tip amount :return: nothing """ print("Thank you so much! We don't make a ton of money.") # Not having a "return" statement causes our function to return None ``` We added the `give_tip` function which takes one parameter, the `tip_amount`. We don’t actually do anything with that parameter… But if we were getting fancier with the coffee shop we might add it to the customer’s bill, we might print it out, or we might berate the customer for being too cheap… Here we just go ahead and blurt out a thanks to the user! Bein’ friendly is important. How do we call this from our `coffee_customer` script? *coffee\_customer.py* ```python # Import the module with coffee_shop functionality import coffee_shop # Output the information we know from the module print("Welcome to", coffee_shop.shop_name) print("Available sizes:", coffee_shop.coffee_sizes) print("Available roasts:", coffee_shop.coffee_roasts) # Get some inputs from the user order_size = input("What size coffee do you want? ") order_roast = input("What roast do you want? ") # Send the order to the coffee shop module shop_says = coffee_shop.order_coffee(order_size, order_roast) # Print out whatever it gave back to us print(shop_says) # See if the user wants to add milk add_milk_response = input("Do you want to add milk (y/n)? ") # Convert the response to lowercase, then check for a "yes" answer if "y" in add_milk_response.lower(): milk_fat = input("What percent milk do you want added? ") shop_says = coffee_shop.add_milk_please(milk_fat) # Print out whatever it gave back to us print(shop_says) # They better give a tip... print("THAT'S GOOD COFFEE! Very good. Your brain is working again.") print("You better give a tip.") tip_amount = input("Tip amount? ") coffee_shop.give_tip(tip_amount) ``` Our function call is there on the last line. ## 5.6. Glossary deterministic : A process that is repeatable and predictable. documentation : A place where you can go to get detailed information about aspects of your programming language. module : A file containing Python definitions and statements intended for use in other Python programs. The contents of a module are made available to the other program by using the *import* statement. pseudo-random number : A number that is not genuinely random but is instead created algorithmically. random number : A number that is generated in such a way as to exhibit statistical randomness. random number generator : A function that will provide you with random numbers, usually between 0 and 1. standard library : A collection of modules that are part of the normal installation of Python. ## 5.7. Exercises 16. Use a `for` statement to print 10 random numbers. ```python import random howmany = 10 for counter in range(howmany): arandom = random.random() print(arandom) ``` [Show Comments](#disqus_thread) 17. Repeat the above exercise but this time print 10 random numbers between 25 and 35, inclusive. 18. The **Pythagorean Theorem** tells us that the length of the hypotenuse of a right triangle is related to the lengths of the other two sides. Look through the `math` module and see if you can find a function that will compute this relationship for you. Once you find it, write a short program to try it out. ```python import math side1 = 3 side2 = 4 hypotenuse = math.hypot(side1,side2) print(hypotenuse) ``` [Show Comments](#disqus_thread) 19. Search on the internet for a way to calculate an approximation for **pi**. There are many that use simple arithmetic. Write a program to compute the approximation and then print that value as well as the value of `math.pi` from the math module.