Python代码第三次调用输出错误,请求问题排查与修正
Python超级英雄名字生成器Bug排查
我正在学习Python的MOOC课程,这是第一次提问。我的代码预期输出应为:
Captain Hawk Doctor Yellow Jacket Moon Moon
但实际输出是:
Captain Hawk Doctor Yellow Jacket Moon Yellow Jacket
请帮忙排查代码和heronames.txt文件中的问题。
原代码
#A common meme on social media is the name generator. These #are usually images where they map letters, months, days, #etc. to parts of fictional names, and then based on your #own name, birthday, etc., you determine your own. # #For example, here's one such image for "What's your #superhero name?": https://i.imgur.com/TogK8id.png # #Write a function called generate_name. generate_name should #have two parameters, both strings. The first string will #represent a filename from which to read name parts. The #second string will represent an individual person's name, #which will always be a first and last name separate by a #space. # #The file with always contain 52 lines. The first 26 lines #are the words that map to the letters A through Z in order #for the person's first name, and the last 26 lines are the #words that map to the letters A through Z in order for the #person's last name. # #Your function should return the person's name according to #the names in the file. # #For example, take a look at the names in heronames.txt #(look in the drop-down in the top left). If we were to call #generate_name("heronames.txt", "Addison Zook"), then the #function would return "Captain Hawk": Line 1 would map to #"A", which is the first letter of Addison's first name, and #line 52 would map to "Z", which is the first letter of #Addison's last name. The contents of those lines are #"Captain" and "Hawk", so the function returns "Captain Hawk". # #You should assume the contents of the file will change when #the autograder runs your code. You should NOT assume #that every name will appear only once. You may assume that #both the first and last name will always be capitalized. # #HINT: Use chr() to convert an integer to a character. #chr(65) returns "A", chr(90) returns "Z". #Add your code here! def generate_name(filename, name): alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" # splitting the name so I can add the intials of the name into a list. z = [] j = name.split() for i in j: z.append(i[0]) # linking the initials to it's index in the alphabet for k in alphabet: if k == z[0]: first = alphabet.index(k) elif k == z[1]: second = alphabet.index(k) + 26 else: pass # reading the super hero names from the file and linking the name to the index file = open(filename, "r") filelist = file.readlines() for i in filelist: global hero if filelist.index(i) == first: supe = i supe = supe.strip() elif filelist.index(i) == second: hero = i hero = hero.strip() else: pass file.close() return supe + " " + hero #Below are some lines of code that will test your function. #You can change the value of the variable(s) to test your #function with different inputs. # #If your function works correctly, this will originally #print: Captain Hawk, Doctor Yellow Jacket, and Moon Moon, #each on their own line. print(generate_name("heronames.txt", "Addison Zook")) print(generate_name("heronames.txt", "Uma Irwin")) print(generate_name("heronames.txt", "David Joyner"))
heronames.txt内容
Captain Night Ancident Moon Spider Invisible Silver Dark Professor Golden Radioactive Incredible Impossible Iron Rocket Power Green Super Wonder Metal Doctor Masked Crimson Omega Lord Sun Lightning Knight Hulk Centurion Surfer Warriors Ghost Hornet Yellow Jacket Moon Ghost Phantom Machine X Doom Z Fist Shadow Claw Torch Soldier Skull Thunder Hurricane Falcon Hawk
问题根源分析
全局变量导致状态残留
使用global hero会让变量在函数多次调用之间保留值。第三次调用generate_name("heronames.txt", "David Joyner")时,若未成功匹配到目标索引,hero会保留上一次调用(Uma Irwin)的结果Yellow Jacket。list.index()逻辑错误filelist.index(i)返回的是列表中第一个匹配元素的索引,而非当前遍历元素的索引。例如heronames.txt中第4行和第35行都是Moon,遍历到第35行时,index()会返回4而非35,导致filelist.index(i) == second(此时second=35)的条件永远不成立,无法更新hero的值。索引计算效率低下
遍历字母表找首字母索引的方式冗余,直接用ord()函数计算更高效。
修正后的代码
def generate_name(filename, name): # 分割名字获取首字母 first_name, last_name = name.split() first_initial = first_name[0] last_initial = last_name[0] # 计算对应的索引:首字母对应0-25,姓氏对应26-51 first_index = ord(first_initial) - ord('A') last_index = ord(last_initial) - ord('A') + 26 # 读取文件内容并预处理换行符 with open(filename, "r") as file: filelist = [line.strip() for line in file.readlines()] # 直接通过索引获取对应名字 supe_part = filelist[first_index] hero_part = filelist[last_index] return f"{supe_part} {hero_part}" # 测试代码 print(generate_name("heronames.txt", "Addison Zook")) print(generate_name("heronames.txt", "Uma Irwin")) print(generate_name("heronames.txt", "David Joyner"))
修正说明
- 移除全局变量,每次调用重新生成结果,避免状态残留
- 用
ord()直接计算首字母索引,无需遍历字母表 - 直接通过索引访问列表元素,彻底规避
list.index()的匹配问题 - 使用
with语句管理文件,自动关闭更安全 - 读取文件时直接处理换行符,减少重复操作
内容的提问来源于stack exchange,提问作者mirror1023
相关产品推荐
相关产品推荐

