2014-09-19 94 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