1 #无尽模式训练你,检验所掌握的面向对象的单词和短语。 2 import random 3 from urllib.request import urlopen 4 import sys 5 6 WORD_URL = "http://learncodethehardway.org/words.txt" #网页中全是单独成行的单词 7 WORDS = [] 8 9 PHRASES = { 10 #创建一个叫%%%的类,并继承%%%。 11 "class %%%(%%%):": 12 "Make a class named %%% that is-a %%%.", 13 #类%%%有一个__init__方法,该方法有self和***两个参数。 14 "class %%%(object): def __init__(self, ***)": 15 "class %%% has-a __init__ that takes self and *** parameters.", 16 #类%%%有一个叫***的函数,该函数有self和@@@两个参数。 17 "class %%%(object): def ***(self, @@@)": 18 "class %%% has-a function named *** that takes self and @@@ parameters.", 19 #给***赋值为类%%%的一个实例。 20 "*** = %%%()": 21 "Set *** to an instance of class %%%.", 22 #从***里调用***函数,传递的参数为self和@@@。 23 "***.***(@@@)": 24 "From *** get the *** function, and call it with parameters self, @@@.", 25 #从***里调用***属性,并将其设置为***。 26 "***.*** = '***'": 27 "From *** get the *** attribute and set it to '***'." 28 } 29 30 # do they want to drill phrases first 31 #由答题者选择是要根据描述编码还是根据代码描述。 32 33 34 #sys.argv为从命令行接收的参数,第一个参数默认为文件名。 35 if len(sys.argv) == 2 and sys.argv[1] == "english": 36 PHRASE_FIRST = True #True表示先打印value,按下任意键后再打印key 37 else: 38 PHRASE_FIRST = False 39 40 41 # load up the words from the website 42 #将词汇们载入到列表WORDS中 43 for word in urlopen(WORD_URL).readlines(): #一行一行从网页中读取数据 44 WORDS.append(word.strip().decode("utf-8")) #删除每一行开始和结尾的空格,只留下单词并加入到words列表中 45 """Python strip() 方法用于移除字符串头尾指定的字符(默认为空格)。 46 str->bytes:encode编码,字符串通过编码成为字节码, 47 bytes->str:decode解码,字节码通过解码成为字符串。""" 48 49 #定义(覆盖描述和代码中预留位置的)函数,参数为片段、短语。 50 #最后返回一个列表results 51 #先将预留放置词汇的位置分类 52 #参数为key或value,两个总是相对 53 def convert(snippet, phrase): 54 class_names = [w.capitalize() for w in random.sample(WORDS, snippet.count("%%%"))] 55 other_names = random.sample(WORDS, snippet.count("***")) 56 """random.sample(sequence, k) 从指定序列中随机获取指定长度的片断。sample函数不会修改原有序列""" 57 results = [] 58 param_names = [] 59 60 for i in range(0, snippet.count("@@@")): 61 #参数的个数为1-3个随机。 62 param_count = random.randint(1,3) 63 #随机到几个参数就从WORDS中获取几个词 64 param_names.append(', '.join(random.sample(WORDS, param_count))) 65 66 #准备好要进行替换的PHRASES 67 for sentence in snippet, phrase: 68 result = sentence[:] 69 #result = [snippet, phrase] 70 #扯句闲话,作者为了片段和代码对应,替换词汇的顺序是固定的。。 71 #用这种方法替换,描述与代码中词汇的顺序肯定是一样的。 72 #fake class names 类名 73 for word in class_names: 74 result = result.replace("%%%", word, 1) #最后一位参数规定每次替换一个,保证%%%不重复。 75 76 #fake other names 对象、方法和其他 77 for word in other_names: 78 result = result.replace("***", word, 1) 79 80 #fake parameter lists 参数名 81 for word in param_names: 82 result = result.replace("@@@", word, 1) 83 84 results.append(result) 85 86 return results 87 88 # keep going until they hit CTRL-D 89 #这里才是重点,是作者的编程逻辑。 90 try: 91 while True: #循环抽题 92 snippets = list(PHRASES.keys()) #字典 keys() 方法:以列表返回一个字典所有的键。 93 random.shuffle(snippets) #随机打乱顺序 94 95 for snippet in snippets: #抽题 96 phrase = PHRASES[snippet] 97 question, answer = convert(snippet, phrase) 98 if PHRASE_FIRST: 99 question, answer = answer, question 100 101 print (question) 102 103 input("> ") 104 print ("ANSWER: %s " % answer) 105 except EOFError: 106 print (" Bye") 107 108 109