Exercise 41 - Weird 'answer' provided during practice

So I am practicing away with oop_test.py and one of the answers it returned seems a little off to me. I’m like 99% sure it returned an incorrect answer but I don’t know why. Could I have transferred the code incorrectly or is there an issue with the code as it is written in the book? Here is the answer in question:

Screen Shot 2020-08-14 at 12.17.22 PM

I can see that for some reason the placeholder “%%%” has passed through the replacement process and is throwing off the results. I can’t for the life of me figure out why it isn’t getting replaced like it is supposed to though.

It looks like maybe you lost a line in the translation. Look for that %%% and everywhere you see it, compare the code with mine. I’m pretty sure you’re not replacing those.

I thought the same thing so I’ve read through the code a few times. I’m pretty confident I’m just missing something and I’m going to walk away for a bit and then come back and recheck it with fresh eyes.

Here’s my code, maybe something will jump out at you more obviously than it is for me:

import random
from urllib.request import urlopen
import sys

WORD_URL = "http://learncodethehardway.org/words.txt"
WORDS = []

PHRASES = {
    "class %%%(%%%):":
      "Make a class named %%% that is-a %%%.",
    "class %%%(object):\n\tdef __init__(self, ***)" :
      "class %%% has-a __init__ that takes self and *** params.:",
    "class %%%(object):\n\tdef ***(self, @@@)":
      "class %%% has-a function *** that takes self and @@@ params.",
    "*** = @@@()":
      "Set *** to an instance of class %%%.",
    "***.***(@@@)":
      "From *** get the *** function, call it with params self, @@@.",
    "***.*** = '***'":
      "From *** get the *** attribute and set it to '***'."
}

# do they want to drill phrases first
if len(sys.argv) == 2 and sys.argv[1] == "english":
    PHRASE_FIRST = True
else:
    PHRASE_FIRST = False

# load up the words from the website
for word in urlopen(WORD_URL).readlines():
    WORDS.append(str(word.strip(), encoding="utf-8"))


def convert(snippet, phrase):
    class_names = [w.capitalize() for w in
                   random.sample(WORDS, snippet.count("%%%"))]
    other_names = random.sample(WORDS, snippet.count("***"))
    results = []
    param_names = []

    for i in range(0, snippet.count("@@@")):
        param_count = random.randint(1,3)
        param_names.append(', '.join(
            random.sample(WORDS, param_count)))

    for sentence in snippet, phrase:
        result = sentence[:]

        # fake class names
        for word in class_names:
            result = result.replace("%%%", word, 1)

        # fake other names
        for word in other_names:
            result = result.replace("***", word, 1)

        #fake parameter lists
        for word in param_names:
            result = result.replace("@@@", word, 1)

        results.append(result)

    return results


# keep going until they hit CTRL-D
try:
    while True:
        snippets = list(PHRASES.keys())
        random.shuffle(snippets)

        for snippet in snippets:
            phrase = PHRASES[snippet]
            question, answer = convert(snippet, phrase)
            if PHRASE_FIRST:
                question, answer = answer, question

            print(question)

            input("> ")
            print(f"ANSWER:  {answer}\n\n")
except EOFError:
    print("\nBye")

Thanks for responding so quickly! I’m trying to power through as much of this book as quickly as I can while still retaining everything and I think I’ve reached the point this week where my eyes are going code-blind and I’m not comprehending what I’m reading as effectively as I’d like. This forum is a huge help whenever I hit a wall or run into a problem of any kind.


I found my mistake, taking a break and coming back a little while later helped me see things more clearly.


Great, yes, breaks are very important. Just for future reference, I ran diff on your post and here’s what it says is different:

12c12
<       "class %%% has-a __init__ that takes self and *** parameters.",
---
>       "class %%% has-a __init__ that takes self and *** params.:",
14,15c14,15
<       "class %%% has-a function named *** that takes self and @@@ parameters.",
<     "*** = %%%()":
---
>       "class %%% has-a function *** that takes self and @@@ params.",
>     "*** = @@@()":
18c18
<       "From *** get the *** function, and call it with parameters self, @@@.",
---
>       "From *** get the *** function, call it with params self, @@@.",
43c43,44
<         param_names.append(', '.join(random.sample(WORDS, param_count)))
---
>         param_names.append(', '.join(
>             random.sample(WORDS, param_count)))
56c57
<         # fake parameter lists
---
>         #fake parameter lists
83d83
<

You read this as < is the line from my code and > is the line(s) from your code.

i think your code is just fine but the problem is maybe sometimes in python its self , i kind of beileive sometimes python did some mistakes compiling your code when you do the seme opration again it runs just fine .

i am a biggener and this is just a biggener answer :slight_smile:

@bestever I’m afraid this is not the case. Python, or any other language, does not have a whimsical approach to compiling or runtime. They follow a procedural mathematical process.

Your working environment may impact execution (for example, if you are running low on resources), or if your code has multiple parallel threads with race conditions occurring, or callbacks, etc. but a program such as this is pretty linear in it’s execution.

Hello there, Thank you bro for explaining that , i really thaught that memory and procecing speed (resources) has nothing to do with that as it should freez not to proceed and make mistakes .

If this is what is going on a machine low in resources will be like a tired or depressed man he will make mistakes . so we maybe need to include this in the code , to tell to the code to fereez when res are not enough.

please correct me if i understand wrong

There’s a few hints where the original poster made a simple typo.

The unexpected output given is our biggest clue. Something went wrong with the %%%, *** and @@@. Not a fatal error, but an error resulting in unexpected text output, and one specific phrase is a problem. That should help narrow things down.

You can see those phrases are defined in a dictionary called PHRASES… from there we can find the specific phrase and check for typos.

And remember dictionaries are key:value pairs separated by commas. The printed book (and probably your editor) has lines wrapping all over the place --not a bad thing, but a skill to always still read these as {key:value, key:value, key:value, key:value, …} no matter what it looks like on the screen or in the book.

Zed also gives a massive clue in his response. He literally shows us what’s different, and the line with the mistake is there! Each line starting with < is his code, compared with > their code. He wants us to find and fix it because that’s the skill we need to develop the most.