为什么我的代码的第三次迭代返回错误



我在Python的MOOC中。这是我第一次在这里发布问题。

我的预期结果应该是打印霍克船长、黄夹克医生和月亮,每个人都有自己的路线。

相反,我让霍克船长、黄夹克医生和月亮黄夹克各穿一条。我的代码出了什么问题?


#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

任何见解都将不胜感激。非常感谢。

if filelist.index(i)是您的问题。你用这个代码说:"告诉我这个列表中具有值CCD_ 2"的项目的索引。它将返回3,因为moon首先出现在那个位置。

正因为如此,而且您正在执行if/elif,所以只有第一个if条件会触发,设置supe两次,而从不设置hero

最后,因为您将hero声明为全局,所以它保留了上一次调用中的最后一个hero值,而不是获得NULLhero/秒名称,而是获得上一个英雄的第二个名称。

您已经确定了第一个和第二个名称所需项目的索引,而不是迭代文件,因此替换

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

supe = filelist[first].strip()
hero = filelist[second].strip()

我不确定您的代码哪里出了问题。您可以稍微简化代码,以便更容易地找出错误的地方。不需要您的两个for循环,因为您可以为列表编制索引。例如:

for k in alphabet:
if k == z[0]:
first = alphabet.index(k)
elif k == z[1]:
second = alphabet.index(k) + 26
else:
pass

成为

first = alphabet.index(z[0])
second = alphabet.index(z[1])

你不需要在字母表中循环,因为Z[i]总是字母表的一部分。

您可以对上一个循环执行类似的操作。

希望能有所帮助。

您的函数过于复杂。以下是我看到的几个错误:

for k in alphabet:
if k == z[0]:
first = alphabet.index(k)
elif k == z[1]:
second = alphabet.index(k) + 26
else:
pass

您可以先使用for index, k in enumerate(alphabet),然后使用index,而不是在alphabet中搜索字母k你已经知道索引了,因为那是你正在迭代的字符串

然而,您根本不需要那个循环。你知道你在找什么信,所以你最好使用

first = alphabet.index(z[0])
second = alphabet.index(z[1]) + 26

for i in fileList相同:由于对fileList进行迭代,您已经知道了i的索引,所以只需使用moon0。然而,你也不需要在这里这样做:你知道你想要的指数,所以只需选择它们:

supe = filelist[first].strip()
hero = filelist[second].strip()

考虑以下简化代码:

def generate_name(filename, name):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
z = [word[0].upper() for word in name.split(maxsplit=1)]
first = alphabet.index(z[0])
second = alphabet.index(z[1]) + 26
with open(filename, "r") as f:
filelist = f.readlines()

supe = filelist[first].strip()
hero = filelist[second].strip()
return supe + " " + hero

我所做的更改:

  • 我使用列表理解来创建z。这基本上将for i in j循环压缩为一行。为了安全起见,我还将字符转换为大写
  • 我在name.split中指定maxsplit=1,因为我们只需要两个值
  • 我用with处理完文件后的关闭。这比打开文件句柄并显式关闭它更像Python

其他一些注意事项:

  • 您不需要定义alphabet:通过从"A"的ASCII代码中减去其ASCII代码(ord(,可以很容易地获得任一名称的第一个字符的索引。例如:first = ord(z[0]) - ord("A")
  • 您可以使用f-string语法来格式化返回值。return f"{supe} {hero}"

最新更新