Mad Libs in Python
Written on Sept. 10, 2012, 12:26 a.m.
As a writer who sometimes dabbles in the creative side of things, I occasionally find myself at a loss for ideas, blindly grasping for the next turning point in a story, a plot twist or even just for how everything begins. I once made the mistake of mentioning this problem to a non-writer: Their response was to buy me an annoyingly heavy box of cards that I was meant to pick from when in need of inspiration — a nice gesture, but who wants to lug around a giant box of cards to a café? Not me.
So I decided I'd try something new. There're always words floating around me, in my head, everywhere, so why not put them to good use? After all, they're just waiting to be used somewhere (or something like that).
And so my Mad Lib generator was born. For those of you born in the 90s or earlier, you'll probably recognize the format: Input words when prompted and get a completed sentence as a result. For me, this sentence doubles as an idea generator, a first sentence of a story waiting to be born.
If you're on Windows, you can play too — just download Python for Windows.
The Parts of a Whole
Building this was like building anything else — an essay, a piece of IKEA furniture — I broke things up to make them more digestible before trying to tackle the entire "problem" all in one go. I started by determining exactly how I wanted my program to play out:
- The program starts and asks the user for a few words
- The user is then given a sentence with the words inserted into the blank spaces of a random sentence
Programs are made up of two main things: variables and functions. Variables are placeholders for data in memory — think of them as "memories" for your computer. Functions are essentially actions — they tell the computer to do something, sometimes involving these memories. Don't worry if this sounds confusing at first — it'll be easier to understand once you have some code in front of you.
How To Do It
Now that you have an idea about what we're going to do, let's talk about how Python will help us do it. Python uses modules to store reusable code, code that includes any number of functions and variables. It works on a "batteries included" philosophy, which means that basic things (actions and objects) are readily available and easily accessible: For example, we can simply import a "random" module with a pre-defined "choice" function instead of having to write our own complicated algorithm.
So where do we write the code to import said module? In a Python file, which uses the extension ".py". To create one, open your favorite text editor — I use OS X so I like TextMate — and create a file for your code, making sure to save it with the ".py" extension. I called mine "pylib.py", but feel free to name your file whatever you want.
Note: If you're on Windows, Notepad++ is a great alternative.
Before we start writing any code, though, let's come up with some Mad Lib-style sentences. Here are two that I used:
- Didn't you hear? (Noun)-(verbing) Noun(s) are the new (color).
- Every (period of time) I like to (verb) my (noun).
Once we've figured out which sentences we want to use, we need to figure out how to fill them in. This is where functions (performed actions) come in — these are what we use to make things happen. With that in mind, let's write a function that asks our user to enter some words and prints out a new sentence.
Working with Functions
It's easy to create functions in Python. The key is to remember that Python is an indentation-based language — anything that happens inside a function needs to be tab-indented to the next level. Take the following, for example:
Def story indicates that we're defining a function named "story" — from this point forward, when we want to use this function, we can simply refer to it by the name we've given it: story(). The parentheses that follow our function's name are used for passing more advanced things and aren't too important at the moment — just make sure they remain there since they're a key element of Python. Lastly, the colon placed after the parentheses indicates that the indented line that follows it are part of the function we've just defined. If you want to try this out for yourself, type the above into your Python console in Terminal, then execute it with story().
Did that work? It might be hard to tell, because our function doesn't actually do anything yet. Let's flesh it out so we can get on with building our Mad Libs:
This has the same format as our old code, but now it actually does what we want! With our new additions, our function now:
- Creates a "template" variable — this is the outline our sentences will be built from. The %()s are placeholders for strings — think of them like the blanks where you have to insert words for Mad Libs.
- Creates a blank dictionary where our users' words will be stored. Dictionaries in Python work the same way as the ones you're used to — for each key (word), there is a value (definition). For us, the key represents the type of word we want, and we store each word our users input as a separate value.
- Asks for and stores a user-defined noun, verb and color in our newly created dictionary. raw_input("") provides our user with a prompt to enter a word, which will be stored in our dictionary.
- Prints a complete sentence — our user's words replace the %()s placeholders, each of which refer to a specific key.
Congratulations, you've just completed your first template function call! Give yourself a pat on the back, then try writing a second one to spice things up a bit — you don't want your user to end up with the same sentence over and over... and over. Mine looked like this (but feel free to play around a bit):
What is .lower()?
The .lower() is a method appended to the end of each dictionary "definition" that forces capitalized words into lowercase. The logic behind this method is a bit complex, but it's a simple way to ensure that your sentences are case-consistent (if you're a perfectionist like me). Without it, the sentence would read:
Every HOUR I like to eAt and Drink my HAPPY CAT.
This outputs a sentence with the format of Every (period of time), I like to (verb) and (verb) my (emotion) (noun). If a user enters HOUR, eAt, Drink, HAPPY, CAT, they will receive:
Every hour I like to eat and drink my happy cat.
Now that we've got a couple stories to choose from, we need to find a way to select a random one so our user doesn't get too bored. In order to do this, we have to group our story functions together and then choose one at random from the group:
This might look at a bit confusing, so let's break it down:
- First line: Import a function (choice) from the built-in "random" module. Since randomization is baked into Python, we simply have to import the function to do it.
- Second line: Put our story functions into an Array. Each item in an Array is separated with a comma, and the entire Array is surrounded by a set of square brackets ().
- Third line: Determine which story function to run — this is done by passing our "stories" Array through the choice() method, which picks a random one. The result is stored inside a new variable called story_to_run.
- Fourth line: Execute story_to_run from start to finish, resulting in a full sentence.
The Completed Code and a Few Notes
Here's a few things to keep in mind:
- Python runs from the top-down, which means that you can't use the choice() method until you've imported it from the "random" module.
- Make sure that each line within a function is properly indented — Python is indentation-based, so things won't work if this isn't done correctly.
- All of the %()s should be accounted for in your dictionary — it's best to have the same number of dictionary keys as %()s spaces in your sentences.
That's all you really need for this program — two functions and a couple of dictionaries. I only went up to two stories, but you can add an unlimited number of them — just make sure you include all of them in your stories Array.
All of that said, take this code and get creative — compose a paragraph... maybe even try to make it loop...