我目前正在攻读GCSE级别的计算机科学,并且接近我的第一次控制评估。上周我们开始学习列表,但为了本周的任务,我们需要使用2D数组创建一个改进的地址簿任务版本。该任务的目的是允许用户将他们需要的人数输入到地址簿中,并向他们询问四条信息。然后将此信息打印到下面的屏幕上。
尽管如此,我在地址簿中输入多个人时遇到错误,错误为list index out of range
。我已经在这里阅读了一些关于上述错误的帖子,但似乎还没有完全理解它。任何援助都将受到高度赞赏。
到目前为止,这是我的代码:
addressbook = ([])
number = int(input("How many people would you like in your address book:"))
for loop in range (0,number,1):
addressbook.append([(str(input("\nPlease enter your full name:")))])
addressbook.append([(str(input("Please enter your home address:")))])
addressbook.append([(str(input("Please enter your hometown:")))])
addressbook.append([(str(input("Please enter your mobile number:")))])
print("\nName:",addressbook[0][loop],"\nHomeaddress:",addressbook[1][loop],"\nHometown:",addressbook[2][loop],"\nMobile number:",addressbook[3][loop])
出现以下错误:
Traceback (most recent call last):
File "C:\Users\Owner\Documents\Computer Science\Python\Address%20book.py", line 23, in <module>
print("\nName:",addressbook[0][loop],"\nHomeaddress:",addressbook[1][loop],"\nHometown:",addressbook[2][loop],"\nMobile number:",addressbook[3][loop])
IndexError: list index out of range
答案 0 :(得分:5)
不要将addressbook
视为关于人的二维信息数组,而应分别考虑每个维度。 addressbook
是一维人。反过来,每个人都是一维信息。
将这种想法引入我们的代码可以使目的更加清晰:
# An address boook is an arary of persons
addressbook = []
number = int(input("How many people would you like in your address book:"))
# Create several persons, adding each to addressbook as we go:
for _ in range(number):
# Create one person:
person = []
person.append(str(input("\nPlease enter your full name:")))
person.append(str(input("Please enter your home address:")))
person.append(str(input("Please enter your hometown:")))
person.append(str(input("Please enter your mobile number:")))
# Add one person to addressbook
addressbook.append(person)
# Now addressbook has several persons
# Display addressbook, thinking of it as two-dim array
for loop in range(number):
print("\nName:",addressbook[loop][0],"\nHomeaddress:",addressbook[loop][1],"\nHometown:",addressbook[loop][2],"\nMobile number:",addressbook[loop][3])
# Display addressbook, thinking of it as array of persons:
for person in addressbook:
print("\nName:",person[0],"\nHomeaddress:",person[1],"\nHometown:",person[2],"\nMobile number:",person[3])
其他说明:
声明addressbook = ([])
与addressbook = []
相同。在这种情况下,括号绝对没有任何作用。
多维数组首先列出行号,列列第二列。也就是说,第一个数字会使您连续,第二个数字会将您带到该行的元素。更简单地说,addressbook[loop][0]
,而不是addressbook[0][loop]
。
表达式range(0, number,1)
与range(number)
相同,后者更易于阅读。
在Python中,如果您需要分配值但不关心它,请使用_
,如下所示:for _ in range(number):
。
表达式str(input(...))
与表达式input(...)
相同,因为input
返回类型为str
的对象。我把它们留下了,因为我认为你的教练需要那种冗长的风格。
到时候,学会将长表达式分成多行。很多人发现超过80个字符的行难以阅读。
每次都提示用户“请输入您的全名”(重点已添加)。据推测,自上一次循环迭代以来,它们的名称没有改变。你实际上是在要求一些第三方的全名。请尝试“请输入他们的全名”或“请输入此人的全名”或其他类似名称。
最后,要意识到计算机程序的阅读频率会高于写入程序。对于拥有数百名贡献程序员的专业维护程序以及为您自己的利益而编写的一次性程序,情况确实如此。使用任何必要的方法与程序的读者进行有效沟通 - 评论,清除变量名称,空格,无论需要什么。
答案 1 :(得分:2)
首先,Rob的上述解释非常适合您的任务。
现在,我想向您展示一些技巧,您可以使用它们,让您的生活更轻松,无需输入OOP概念并尽可能保持代码简单,无需错误捕获或无论如何。
from collections import namedtuple
Person = namedtuple(
'Person',
('full_name', 'home_address', 'home_town', 'mobile_number')
)
person_print_template = '''
Full Name: {full_name}
Home Address: {home_address}
Home Town: {home_town}
Mobile Number: {mobile_number}'''
persons = []
number = int(input('How many people would you like in your address book: '))
for iteration in range(number):
full_name = input('\nFull name: ')
home_address = input('Home address: ')
home_town = input('Home town: ')
mobile_number = input('Mobile number: ')
person = Person(full_name, home_address, home_town, mobile_number)
persons.append(person)
for person in persons:
print(person_print_template.format(**person._asdict()))
collections.namedtuple 是一种定义非常简单的可重用对象的方法,并提供了一个返回字典的_asdict()方法。
在python中,将**放在字典前可以解压缩每个字典键和值,然后将其传递给模板,str.format()将替换“{ key_name}“按其值。
同样,这是一种格式化字符串输出的强大方法,特别是在多行。=时,无论是对于Web还是对于命令行输出,如此处。
答案 2 :(得分:2)
from collections import OrderedDict
# this is only necessary if you need your fields to always be in the
# same order when they're printed. Otherwise ignore and have Person
# inherit from dict
FIELDS = ["full name", "address", "hometown", "mobile number"]
class Person(OrderedDict): # see note above
def __init__(self, keys=None):
super().__init__() # this is magic that makes the OrderedDict work
if isinstance(keys, dict):
self.update(keys)
# this allows you to pass in a normal dict like you can for any
# other dict or ordered dict, and only prompt otherwise
else:
for key in keys:
self[key] = input("Please enter your %s: " % key)
def __str__(self):
"""The __str__ function describes how str(self) looks. I'm defining
it here to mimic the way Apero used his person_print_template string"""
output_strings = []
for key,value in self.items():
output_strings.append("{}: {}".format(key, value))
return "\n".join(output_strings)
# this is equivalently:
## return "\n".join(["{}: {}".format(key,value) for key,value in self.items()])
class AddressBook(list):
def __init__(self, size=None):
if size is None:
size = int(input("How many entries are in this address book? "))
for entry in range(size):
global FIELDS
self.append(Person(FIELDS))
def __str__(self):
return "\n\n".join([entry for entry in self])
# double spaced for readability
if __name__ == "__main__":
book = AddressBook()
print()
print(book)
# OUTPUT:
How many entries are in this address book? 2
Please enter your full name: Adam Smith
Please enter your address: 123 Some St.
Please enter your hometown: Eugene, OR
Please enter your mobile number: 555-867-5309
Please enter your full name: John Smith
Please enter your address: 987 Hello World, Ave.
Please enter your hometown: Camelot (tis a silly place)
Please enter your mobile number: 555-789-1234
full name: Adam Smith
address: 123 Some St.
hometown: Eugene, OR
mobile number: 555-867-5309
full name: John Smith
address: 987 Hello World, Ave.
hometown: Camelot (tis a silly place)
mobile number: 555-789-1234
您当然可以更改格式以适应。我会用str.format方法指出你,这样你就可以做出很好的理由来证明你的字符串
# # inside Person.__str__
for key,value in self.items():
global SCREENWIDTH # perhaps 50?
output_strings.append("{0}: {1:>{2}}".format(key,value, SCREENWIDTH - len(str(key)) - 1))
full name: Adam
address: blah
hometown: doohickey
mobile number: 1234
可能是AddressBook上的一个标志。 init 在给定现有Person
个对象列表的情况下作为备用构造函数。
class AddressBook(list):
def __init__(self, argument=None, _prompted=True):
if _prompted:
size = argument # just for clarity
self.from_prompt(size)
else:
lst = argument # just for clarity
self.from_list(lst)
def from_prompt(self, size):
# exactly as __init__ is above
def from_list(self, lst):
self.extend(lst)
使用OOP可以完成许多有趣的事情。我个人喜欢它们只是因为Python的鸭子打字只有在我能控制听到什么样的庸医以及制作什么样的庸医时变得更强! :)
答案 3 :(得分:0)
改为使用
for loop in range (0,number,1):
addressbook.append([])
addressbook[-1].append([(str(input("\nPlease enter your full name:")))])
addressbook[-1].append([(str(input("Please enter your home address:")))])
addressbook[-1].append([(str(input("Please enter your hometown:")))])
addressbook[-1].append([(str(input("Please enter your mobile number:")))])
print("\nName:",addressbook[-1][0],"\nHomeaddress:",addressbook[-1][1],"\nHometown:",addressbook[-1][2],"\nMobile number:",addressbook[-1][3])
您的代码存在的问题是您使用的是单维列表。对于每个循环,您将项目添加到地址簿中,因此在循环的2次迭代之后它将看起来像这样
["name1","addr1","hmtown1","mob1","name2","addr2","hmtown2","mob2"]
因此,解决方案是为循环中的每个迭代添加一个空列表,并为该空列表添加详细信息,以便结构看起来像这样
[["name1","addr1","hmtown1","mob1"],["name2","addr2","hmtown2","mob2"]]
在每次迭代中,我们通过地址簿[-1]访问最后一个列表,然后将项目附加到最后一个列表,类似地使用地址簿[-1] [0]访问项目。
希望这有助于您了解问题。