简体   繁体   中英

for statement and replace keyword in the code

I am very new to Python, actually this is my wk2 trying to follow the book, Learn Python the Hard Way .

For the code in ex41.py, I have two questions.

  1. I don't quite understand why it has the following statement:

    for i in range(0, snippet.count("@@@")):

    since snippet.count("@@@") will always be 1, then I would have only 1 value which is 0. Why do we loop through it anyway? Why can't we go straight to set variables param_count and param_names ?

  2. I am also confused by:

     for word in param_names: result = result.replace("@@@", word, 1) 

    I know param_names is a list of words which up to three words, but since @@@ only show up once in both snippet and phrase, how can it get replaced more than 1 times?

Thanks,

import random
from urllib 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 *** parameters.",
"class %%%(object):\n\tdef ***(self, @@@)":
 "class %%% has-a function named *** that takes self and @@@ parameters.",
"*** = %%%()":
 "Set *** to an instance of class %%%.",
"***.***(@@@)":
 "From *** get the *** function, and call it with parameters self, @@@.",
"***.*** = '***'":
 "From *** get the *** attribute and set it to '***'."
}


PHRASE_FIRST = False
if len(sys.argv) == 2 and sys.argv[1] == "english":
    PHRASE_FIRST = True


for word in urlopen(WORD_URL).readlines():
    WORDS.append(word.strip())

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[:]



        for word in class_names:
            result = result.replace("%%%", word, 1)

        for word in other_names:
            result = result.replace("***", word, 1)

        for word in param_names:
            result = result.replace("@@@", word, 1)

        results.append(result)

    return results


try:
    while True:
        snippets = 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

            raw_input("> ")
            print "ANSWER: %s\n\n" % answer
except EOFError:
    print "\nBye"

Referring to your question 2 ( result = result.replace("@@@", word, 1) ):

Normally, you won't replace it more than one time.

With the optional argument "1", only the first "@@@" gets replaced.

For example:

str = "Hello @@@ hello @@@."

print str.replace("@@@", "world", 1)

print str.replace("@@@", "world", 2) 

Hello world hello @@@.

Hello world hello world.

But in this case it is a loop and it replaces one item at each loop.

str = "Hello @@@ hello @@@."

Loop1

str = "Hello world hello @@@."

Loop2

str = "Hello world hello world."

Finally, in case that you are wondering why the @@@ gets replaced by more then one word.

Take a look to the Join String Method:

param_names.append(', '.join(random.sample(WORDS, param_count)))

What this method basically does, is transform several strings to one string.

print ', '.join(["Word1", "Word2"])
Word1, Word2

param_names contains subsequent names of parameters, so if you have ['param1', 'param2'] and a string '(@@@, @@@)' you want the first replace to be result.replace("@@@", 'param1', 1) so it will replace only the first occurrence of @@@ resulting in '(param1, @@@)' . Then, you want to replace the second @@@ to have '(param1, param2)' . Without the constraint you would end up with '(param1, param1)' , ie all occurrences of @@@ would be replaced with the name of the first parameter. The same applies for all other place holders (classes and "others").

The fact that something seems redundant for some particular input data does not imply that it's redundant in general. It is needed for other possible inputs than the example in the script, without this the algorithm would be incorrect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM