Beginner education Python

Let’s Make a Shakespearean Insult Generator in Python

“Heaven truly knows that thou art false as hell.”

Photo by Monica Silvestre on

It’s Monday night, which can mean only one thing: it’s time to write a Shakespearean insult generator in Python.

(I’m very cool.)

Let’s face it. If rap battles had existed in his time, the bard would have blown away the competition. From the vicious (“Thou art a boil; a plague sore” (King Lear)), to the scornful (“Thine face is not worth sunburning” (Henry V)), to the downright scandalous: (“Villain, I have done thy mother” (Titus Andronicus)), Shakespeare’s insults were ruthless, devastating, and, frankly, pretty weird.

In this article, we’ll design and create a Python program that returns a randomly generated Shakespearean insult using external text files. Let’s get started.

Step 1. Find some insults

This part is easy. A quick Google search brought me to the awesome website “No Sweat Shakespeare”, which featured a handy Shakespearean insult generator, which I used to create the table below.

Here’s the basic format we’ll use to create a random Shakespearean insult:

Column 1 (adjective) + Column 2 (more elaborate adjective) + Column 3 (noun)

To make things easier, I recommend splitting these columns into three text documents (one for each column.)

COLUMN 1          COLUMN 2              COLUMN 3
Artless           base-court            apple-john 
Bawdy             bat-fowling           baggage
Beslubbering      beef-witted           barnacle
Bootless          beetle-headed         bladder
Churlish          boil-brained          boar-pig
Cockered          common-kissing        bugbear
Clouted           crook-pated           bum-bailey
Craven            dismal-dreaming       canker-blossom
Currish           dizzy-eyed            clack-dish
Dankish           dog-hearted           clotpole
Dissembling       dread-bolted          coxcomb
Droning           earth-vexing          death-token
Errant            elf-skinned           dewberry
Fawning           fat-kidneyed          flap-dragon
Fobbing           fen-sucked            flax-wench
Froward           flap-mouthed          flirt-gill
Frothy            fly-bitten            foot-licker
Gleeking          folly-fallen          fustilarian
Goatish           fool-born             giglet
Gorbellied        full-gorged           gudgeon
Impertinent       futs-griping          haggard
Infectious        half-faced            harpy
Jarring           hasty-witted          hedge-pig
Loggerheaded      hedge-born            horn-beast
Lumpish           hell-hated            hugger-mugger
Mammering         idle-headed           jolthead
Mangled           ill-nurtured          lewdster
Mewling           knotty-pated          lout
Paunchy           milk-livered          maggot-pie
Pribbling         motley-minded         malt-worm
Puking            onion-eyed            mammet
Puny              plume-plucked         measle
Qualling          pottle-deep           minnow
Rank              pox-marked            miscreant
Reeky             reeling-ripe          moldwarp
Roguish           rough-hewn            mumble-news
Ruttish           rude-growing          nut-hook
Saucy             rump-fed              pigeon-egg
Spleeny           shard-borne           pignut
Spongy            sheep-biting          puttock
Surly             spur-galled           pumpion
Tottering         swag-bellied          ratsbane
Unmuzzled         tardy-gaited          scut
Vain              tickle-brained        skainsmate
Venomed           toad-spotted          strumpet
Villainous        unchin-snouted        vartlot
Warped            weather-bitten        vassal

Step 2. Make an outline

First, let’s figure out what we want the program to do.

These general tasks will be our functions:

  • Display a greeting (we’ll call this function ‘show_header’)
  • Return a line from each document (let’s call this function ‘get_insults’)
  • Format these lines to produce a new insult (our ‘main’ function will perform this task)

Now let’s break these down further. This will be our pseudocode:

#Import random module
#Define global constants

#Define main function
    #Initialize sentinel value to 'y'
    #While sentinel value == 'y':
        #Call the show_header function
        #Call get_insults function 3x (one for each column)
        #Remove newline character from each insult
        #Concatenate insults and display result
        #See if user wants to get another insult ('y' for yes,
        #any other key for no). This will be the sentinel's new

#Define get_insults function (takes a file as argument)        
        #Create empty list
        #Open file for reading
        #Read through document, append each line to empty list
        #Close file
        #Find length of the list
        #Generate a random number between 0 and the length of the     
        #list - 1
        #Use this number to return a random item from our list

#Define show_header function
        #Display greeting

#Call the main function

Step 3. Import random module and define global constants

Reusability and readability are important in coding. That’s why it’s good practice to write global constants into your code if you need to work with specific values throughout your program (and if those values could change).

For our purposes, we’re using three text files throughout our code, so let’s make those file names global constants. If we want to use different files in the future, this allows us to make that change without having to go through each function and painstakingly edit each instance.

We’ll also need to use Python’s built-in ‘random’ module, so let’s import that as well.

import random

FIRST_COLUMN = "Column1_file.txt"

SECOND_COLUMN = "Column2_file.txt"

THIRD_COLUMN = "Column3_file.txt"

Step 4. Write the functions

1. The get_insults function

Since we want to use this function to open files, let’s make ‘file’ a parameter of this function. (See line 1)

Line 2 creates an empty list. This is where we’ll store data from the list temporarily when we read through our file.

Line 3 opens the file in ‘read’ mode. But what happens if the file can’t be opened? What if the file has been moved or renamed?

1 def get_insults(file):
2         insult_list = []
3         openfile = open(file, 'r')

Right now, if there’s an issue opening the file, our program will crash.

We can prevent this by writing a try-except statement (lines 3 through 6):

1 def get_insults(file):
2         insult_list = []
3         try:
4                 openfile = open(file, 'r')
5         except IOError:
6                 print("Unable to open file.")

Now, if the file can’t be opened (i.e., if an IOError occurs), our program will display the message “Unable to open file”.

Next, let’s begin processing our file. Line 7 assigns the variable ‘line’ to the first line of the file. This allows us to start a ‘while’ loop, which repeats until ‘line’ is an empty string (which means we’ve reached the end of the document).

7         line = openfile.readline()
8         while line != '':
9                 insult_list.append(line)
10                line = openfile.readline()
11        openfile.close()
12        num_items = len(insult_list)
13        index = random.randint(0, num_items - 1)
14        return insult_list[index]

In line 9, our program appends each line in our file to our temporary list (insult_list). Once the document ends (i.e., ‘line’ = ‘ ‘), we close the file.

Awesome. Okay — now let’s get our phrase from the file. In line 12, we find the length of our list. Line 13 generates a random number that’s at least 0 and less than our list length. Finally (we’re nearly done, friends!), in line 14, we index into our list using this random number, and return a random phrase.

2. The show_header function

This one’s pretty self explanatory. (Please don’t judge the lack of artistry — I did my best.)

def header():

16  print("----------------------------------------------")
17  print("Welcome to the Shakespearean Insult Generator!")
18  print("----------------------------------------------")
19  print()

3. The main function

*Cracks knuckles* Time to tie it all together.

20 def main():

21    #Initialize sentinel value to 'y'
22    #While sentinel value == 'y':

23    again = 'y'
24    while again.lower() == 'y':

25            #Call the show_header function
26            show_header()

27            #Call get_insults function 3x (one for each column)
28            first_column = get_insults(FIRST_COLUMN)
29            second_column = get_insults(SECOND_COLUMN)
30            third_column = get_insults(THIRD_COLUMN)

31            #Remove newline character from each insult
32            first_word = first_column.rstrip()
33            second_word = second_column.rstrip()
34            third_word = third_column.rstrip()

35            #Concatenate insults and display result
36            print("Here's my next random insult:")
37            print(f"{first_word} {second_word} {third_word}! \n")

38            #See if user wants to get another insult ('y' for
39            #yes, any other key for no). This will be the
40            #sentinel's new value
41            print("Would you like to generate another insult?")
42            again = input("(Press 'y' for yes, or " +
43                          "any other key for no) ")
44     print("Thanks for using the Shakespearean Insult Generator!")

Congrats, friend. You’ve just written what’s probably your first (but possibly not your last) Shakespearean insult generator in Python. Great job — go get yourself a coffee.

Thanks to No Sweat Shakespeare (and of course, the bard himself).

This article was originally published in gitconnected’s publication, LevelUp Coding. You can read it here.

By Ayla Yersel

Humanities nerd learning to code.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s