2014-09-19 93 views
2

我目前正在攻读GCSE级别的计算机科学,并且正在接近我的第一个受控评估。上周我们开始学习关于列表的知识,但为了本周的分配目的,我们需要使用2D阵列创建地址簿任务的改进版本。该任务的目的是允许用户将他们需要的人员输入到地址簿中,并要求他们提供四条信息。这些信息将被打印到下面的屏幕上。Python;列表索引超出范围[地址簿任务]

是因为它可能,我进入一人以上时到地址簿,与错误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

不要把你的代码放在屏幕截图中。将它*复制到您的问题*中,并包含错误的*完整回溯*。 – 2014-09-19 21:01:56

+3

例如,我们无法复制和粘贴屏幕截图来查看您做错了什么。没有人可以*搜索代码。 – 2014-09-19 21:02:57

+0

什么是循环?通过追加的外观,您不会创建2D数组。我们需要看到你的整个代码。 – 2014-09-19 21:08:02

回答

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个字符的行很难阅读。

您提示用户“请输入您的全名”(每次强调加)。据推测,自从上一次循环迭代以来,他们的名字没有改变。你实际上是要求一些第三方的全名。尝试“请输入他们的全名”或“请输入此人的全名”或其他。

最后,意识到计算机程序的读取次数比写入的次数要多。对于拥有数百名贡献程序员的专业维护程序,以及为了您自己的利益而编写的一次性程序,情况也是如此。使用任何必要的手段与您的程序的读者进行有效的交流 - 评论,清楚的变量名称,空白,无论如何。

+0

非常感谢!您的建议非常有帮助,我肯定会在整个课程期间考虑您的提示。尽管如此,关于显示地址簿的最后一行似乎不起作用,并且实际上返回了错误。我已经删除了该行,并且程序在没有它的情况下似乎可以正常工作。这条线的目的是什么? – ComputingStudent213 2014-09-19 21:54:19

+0

你的意思是开始print(“\ nName:”,person [0] ...'的行吗?我的答案中的程序在Python 3.4.0中对我完全适用。 – 2014-09-19 22:08:38

+0

我刚刚重新测试过它,并且它似乎我有一个语法错误,对此感到遗憾,但是,这个循环的目的是什么?它是否仅仅打印列表'person'? – ComputingStudent213 2014-09-19 22:16:55

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次迭代循环它看起来smthing这样

["name1","addr1","hmtown1","mob1","name2","addr2","hmtown2","mob2"] 

的添加项目到地址簿所以不是解决办法是在环路和到空的列表中添加一个空列表每次迭代我们添加细节,这样的结构是这样的

[["name1","addr1","hmtown1","mob1"],["name2","addr2","hmtown2","mob2"]] 

在我们通过通讯录进入最后名单每次迭代[-1],然后追加项目到最后一个列表,同样访问使用通讯录[项目 - 1] [0]。

希望这有助于你理解问题。

+2

您需要解释为什么这会起作用 - 使用-1的索引对于新的python用户并不明显。 – 2014-09-19 21:10:58

+1

但是为什么我需要使用它?如果可能的话,我宁愿解释为什么,而不仅仅是简单的答案。 – ComputingStudent213 2014-09-19 21:20:56

+0

编辑帖子。感谢您的建议:P – 2014-09-19 21:24:20

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或命令行输出(如此处)。

+1

这非常有帮助,而且非常耐人寻味。我肯定会在课程的其余部分考虑collections.namedtuple,因为我确信它对于effi代码效率。我很确定,我的老师也会很高兴看到我在今年晚些时候的受控评估中利用这样的编码方面。 – ComputingStudent213 2014-09-19 22:32:20

2

Rob的答案,正如Apero所言,是完美的。然而,由于Apero函数式编程解决您的格式,我将在OOP解决这个问题(主要是因为我喜欢抽象的功能代码:d)

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 

可能是一个标志。 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的鸭子打字才喜欢它们,只有当我可以控制要听什么样的嘎嘎声以及制作什么样的嘎嘎声时才会变得更加强大! :)

+0

哇,这是非常令人难以置信的编码;虽然我的水平以上的方式!尽管如此,感谢您的建议。 – ComputingStudent213 2014-09-20 23:09:31