I was bashing my head against a wall (figuratively) and it was almost time to give up. Working through a problem in Chapter 8 of Automate the Boring Stuff with Python, I was (as usual) feeling pretty dumb.
The assignment is to create a simple Mad Libs program that reads a text file and asks the user to provide input for every NOUN, ADJECTIVE, and VERB in the sentence, then replace each word with the user’s input, save the new file and print out the resulting sentence to the console.
And it was driving me bananas.
As I saw it pretty quickly, the best way to do this would be to:
Create a filepath variable (path), go to that path, read the string from a file into a new variable (content), convert that string to a list, iterate through the list and ID the important words, replace those words (NOUN, VERB, etc.) with user input, then re-join the list into a string, write the string to a file, then read that file.
Perhaps not surprisingly, I ran into some hiccups along the way and had to turn to Stack Overflow.
Ah, Stack Overflow, where every answer leads to a new question. As usual with SO, there were several answers almost immediately (some more polite than others). Some misunderstood what data type we were dealing with due to the fact that I had to rejigger the code to make sure my file path remained anonymous…
At the heart of the issue was this: I was iterating through a list and trying to replace certain words in the list with user input:
content = 'The ADJECTIVE panda walked to the NOUN and then VERB.'
content = content.split()
for word in content:
if word == word.upper() and len(word) > 1:
word = word.replace('.','')
response = input(f"Enter a {word} \n")
[response for word in content if response]
When running the code, the response I kept getting was, nothing has changed: 'The ADJECTIVE panda walked to the NOUN and then VERB.'
One issue someone pointed out was that the swap I was creating was never assigned to anything, so it was just garbage data that would never be seen.
The best suggestion to my mind was maybe a little clunky, but it made it crystal clear to everyone (even me) what was going on in this block:
content = 'The ADJECTIVE panda walked to the NOUN and then VERB.'
content = content.split()
new_content = []
for word in content:
if word == word.upper() and len(word) > 1:
word = word.replace('.', '')
response = input("Enter a replacement for {}: ".format(word))
new_content.append(response)
else:
new_content.append(word)
new_content = " ".join(new_content)
Lesson learned: If you’re replacing something inside a variable, create a new variable for the new stuff to avoid confusion… At the very least, to make it clear to yourself. As I progress as a developer, someday I might be able to get fancy in certain instances, but for now this just makes sense.
Another key lesson is to slow down and consider everything that needs to happen. My initial code block is a decent example of me being in my head…. I knew what had to happen in the parameters I had set up, but I was ready to close up shop before everything was completely done… namely: encapsulating and outputting the changes the program was making.
Incidentally, even making these changes didn’t completely solve the problem… I had a second error in the final block of code:
ML1 = open('/Users/XXXXXX/Desktop/MadLibs/ML1.txt', 'w')
ML1.write(new_content)
ML1.close()
This first line had initially referred to a ‘path’ variable declared earlier, but I found when I replaced it with the actual path, it correctly overwrote the file in the right destination and created the new file.
Libs can be maddening that way.