A Pythonic Valentines Day

One of my biggest challenges in growing my Python skills is time.  I have a full-time office job, a wife, and am active in mentoring high school and college students in our church’s youth and college group.  I also try to exercise and stay in shape, as I am no longer, by any stretch of the imagination, a young man. These activities are all vital and important to me, but I often find many days can slip by without me doing a single line of code, and all the cool things I learned a couple of weeks ago start to get fuzzy in my mind.  My tendency is to want to hammer away at a single, huge, complicated goal, such as my Tkinter/database interface, while my everyday Python skills languish, such as finding values in a dictionary or reading from a file. Therefore, I’ve decided that in between progress on gallant quests such as The Silvery Mystery Table or the GUI for the Application of Coolness, I’m going to continue working through the Real Python course, chapter by chapter.  After all, I did spend money on it, the least I can do is use it!  I have already found that it’s a great way to learn and reinforce those everyday skills that can make Python useful for me in a more immediate way.   So, without further ado, here’s my latest silly, yet fun and educational, effort.

Now that February is upon us, the Valentines Day displays at stores are out in full force.  But, for an aspiring Pythonian, what better way to impress his or her significant other than code that generates romantic poetry? I recently completed this assignment for the Real Python course, to test my understanding of lists, just in time to shore up the skills of shaky Shakespearians. There was a word list assigned which I originally hard-coded in as a dictionary, but I took it a step higher and wrote in some code to read word lists from a *.csv file.  That way, I was able to ask my wife Donna to supply the romantic words of her choice in a simple Notepad file, and voilà! – with the press of F5, out came words to woo her by!  Well, not quite…but at least it was a learning and skill-strengthening experience, and I was able to get her interested in my coding progress.  And as of now, we’re still married, so the poems couldn’t have been that bad.

Here’s the code, followed by a sample word list that can be copied and pasted into a *.csv text file.  Enjoy, and Happy Valentines Day!

"""Poetry 3.0
My project from "Real Python" 6.1.
In my humble opinion my code is more efficient than the "official"
solution.
This program reads lists of words from a *.csv file and uses them
to create random poems."""

from random import choice
import csv
import os

# A dictionary of word types. Key = word type, values = word list.
# We are creating empty lists in preparation for appending from
# CSV file

word_lists = {"nouns":[],"verbs":[],"adjectives":[],
              "prepositions":[],"adverbs":[]}

# The path to the folder where this code and the *.csv file reside.
# Change this as needed.
myPath = "D:\Dropbox\RealPython"

"""Assume the *.csv file is "words.csv." Each row is a set of words.
The first column of each row must be the word type. Example:
nouns,delight,smile,eyes,Valentine,heart,bowels,liver,hair
verbs,puckers,tinkles,blossoms,smiles,glow,dash
"""
with open(os.path.join(myPath, "words.csv"), "rb") as myFile:
    myFileReader = csv.reader(myFile)
    for row in myFileReader:
        try:
            if row[0] == "nouns":
                for w in range(1,len(row)):
                    word_lists["nouns"].append(row[w])
            elif row[0] == "verbs":
                for w in range(1,len(row)):
                    word_lists["verbs"].append(row[w])
            elif row[0] == "adjectives":
                for w in range(1,len(row)):
                    word_lists["adjectives"].append(row[w])
            elif row[0] == "prepositions":
                for w in range(1,len(row)):
                    word_lists["prepositions"].append(row[w])
            elif row[0] == "adverbs":
                for w in range(1,len(row)):
                    word_lists["adverbs"].append(row[w])

        except (IndexError):
            break

def create_list(kind, num):
# type = string = "nouns", "verbs", etc.
# num = number of words of type

    word_list = []

    # Add the first random choice word to the list
    selection = choice(word_lists[kind])
    word_list.append(selection)

    # Add the additional required words
    for n in range(0,num-1):

        # If the selected word is already in the list,
        # choose another random word.
        while selection in word_list:
            selection = choice(word_lists[kind])

        # Now that we know the selected word isn't already in the list,
        # append it.
        word_list.append(selection)

    return word_list

def makePoem():
    # Create the differnt types of word lists
    poem_nouns = create_list('nouns',3)
    poem_verbs = create_list('verbs',3)
    poem_adj = create_list('adjectives',3)
    poem_prep = create_list('prepositions',2)
    poem_adv = create_list('adverbs',1)

    # Check if first letter of first adjective is a vowel;
    # if it is, the starting word is "An", else it's "A".
    if "aeiou".find(poem_adj[0][0]) != -1:
        article = "An"
    else:
        article = "A"

    poem = "{} {} {}".format(article, poem_adj[0], poem_nouns[0]) + "\n" + "\n"
    poem = poem + "{} {} {} {} {} the {} {}".format(article, poem_adj[0],
                                            poem_nouns[0],poem_verbs[0],
                                            poem_prep[0],poem_adj[1],
                                            poem_nouns[1]) + "\n"
    poem = poem + "{}, the {} {}".format(poem_adv[0],poem_nouns[0],
                                         poem_verbs[1]) + "\n"
    poem = poem + "the {} {} {} a {} {}".format(poem_nouns[1],poem_verbs[2],
                                        poem_prep[1],poem_adj[2],poem_nouns[2]) + "\n"

    return poem

print makePoem()

Sample word list:

nouns,delight,smile,eyes,Valentine,heart,bowels,liver,hair,sunshine,hobbit,sky,dance,arms,arrow
verbs,puckers,tinkles,blossoms,smiles,glowing,lights,dashing,flashing,soaring,dashing
adjectives,gracious,ruby red,fastidious,quirky,passionate,toffeebrown,deep,cherished,straight,fierce,shiny,ecstatic,monstrous,golden,elvish
prepositions,of,by,after,along,from,to,toward,for,amid,beside,in,into,like,near,over,up,with,soon,somewhere,rather,terribly,
adverbs,succinctly,fetchingly,intently,magically,adoringly,recklessly,effortlessly,eagerly,gracefully