Join Barron Stone for an in-depth discussion in this video Select tools from modules, part of Programming Foundations: Real-World Examples.
- There's a common saying that a smart programmer is a lazy programmer. What that means is clever programmers don't waste time rewriting routines that already exist. There's no need to reinvent the wheel if it's already been invented for you. Almost all programming languages come with a standard library of code for accomplishing common programming tasks. And you should learn how to use the existing libraries because it'll save you a lot of time. In Python, those libraries come in the form of packages and modules which give you access to a wide range of functions and classes to use for different tasks.
Other languages call them libraries or patches. Built-in functions we might use to write our program are organized within modules and packages just like the tools in my garage. One of my brake lights is out, and in order to fix the problem, I'm going to need the right tools for the job. I keep different types of tools organized into different toolboxes. This toolbox holds my screwdrivers while this one holds my wrenches. I need to perform the function of replacing my taillight so I'll grab the modules I need and carry them over here by my car.
To use a screwdriver, I'll reach into this toolbox and I'll select the specific screwdriver that I want to use. And when I need to use a wrench, I'll reach into this toolbox and select the specific wrench that I needed from it. If I'm planning to use several different wrenches as I fix my car, then it makes sense for me to do this and import the entire module by carrying the toolbox over to my car. But if I only need to use a single wrench for this job, then importing the entire module would be overkill and it could be cumbersome to carry the toolbox over and access it every time I want to use that same wrench.
For example, if I realize that I need a roll of duct tape to fix my car, because duct tape fixes everything, I can come over here to this box full of tape, glue, and other assorted adhesives. Since duct tape is the only item I'll need from it, I'll just grab the roll of tape and leave the rest of items in the box. Some languages require you to import entire modules just to use one tool. Others, like Python, give me the flexibility to import entire modules or just select the specific tool that I need.
Python doesn't have hardware tools like wrenches or screwdrivers but it does come with an assortment of software modules. First, we'll need to pick a module to use. You can find information about all of the standard Python modules on the docs.python.org/3 website under the Global Module Index. This is a list of the various modules that are available to use in Python 3. One module that I use frequently is the random module which can be used to generate random numbers. This page describes the random module and provides information about the functions and classes it includes.
It even gives a few basic examples about how to use the module down near the bottom of the page. Since the random module is one of my personal favorites, I'll use it now. For this demonstration, I'm just going to use the interactive shell to give commands to the Python interpreter. Importing an entire module is as simple as typing the command import followed by the name of the module. In this case, I'll import the random module. With that imported, I can access and use objects from the random module in this Python session. The syntax for accessing functions from within the module is to type the module name, dot, the name of the function.
So I can use the randint function from the random module which returns a random number from within a range by typing random.randint. This function takes two arguments, a high and a low range value, and when executed, the function will return a random integer in that range, in this case, between 1 and 20. Since I imported the entire random module, I have to reference it every time I want to use something from it. If I try using randint without specifying that it comes from the random module, then I get an error message because the function name has not been defined within my session.
It can be cumbersome always having to type random.randint every time I want to use that function. If randint was the only function that I needed from the random module, then I could import just that one function by typing from random import randint. This will only import the randint function and it will allow me to access it directly without having to reference the random module every time. Now, I can just type randint (1,20). And it works! And it's more convenient.
Now, as a personal rule of thumb, if I'm going to be using several functions or classes from a certain module, then I'll go ahead and import the entire module. I only use the From module import object statement if I only need one, maybe two objects, from a certain module. One reason I try to limit my use of the From statement is because you have to be careful that the name of the object you're importing doesn't conflict and have the same name as another object in your program. For example, if my program had another object in it named randint, perhaps a variable I had created to store some random value, that would cause confusion.
I can actually demonstrate this sort of conflict using just the random module because it has a function in it that's also called random which is used to generate random numbers between zero and one. Since I've already imported the entire random module, I can access the random function by typing random.random, and it will give me a random number. If I decided to import the random function using a From statement, from random import random. This statement is perfectly legit but it creates the potential for a future mess.
The name random which previously pointed to the entire random module now points to that single random function. The good news is that now I can directly use the random function and that's convenient, but the bad news is that if I try to access anything else from the random module, such as randint, it'll now cause an error because the name random points to a function instead of the module. In a small, simple program, you can probably recognize the situation before it becomes a real issue. However, as your programs grow in size and stretch across multiple modules, it can become more and more difficult to catch this sort of issue.
Python does give us a way to work around this sort of name conflict issue and that is to assign the object you're importing to a different name. I'll import the random module again, but this time using a different name by using a keyword as. I'll name it rand. Now, it can reference the random module by using the name rand to access functions like randint and I can still use the random function with just the basic name random. I've sidestepped the name conflict between the random function and the random module by importing the module as a different name.
It's important to pay attention when you're importing and using modules to avoid unintentionally creating name conflicts with other parts of your program.
- Reusing functions
- Local vs. global variables
- Creating and naming custom objects
- Class inheritance
- Modules and packages
- Multidimensional lists and tuples
- Queues and stacks
- Creating and combining sets
- Storing data in dictionaries
- If/else and switch statements
- For vs. while loops
- Error handling
- Polling and event-driven programming