[英]Python TypeError in traversing a list
我正在自學Python 3.2,並嘗試制作一個與名稱列表匹配的程序。 pList是一個多維列表,在第0列有一個字符串,在第1列有一個整數,在第2列有一個布爾值。但是,每當我嘗試調用此函數時(僅當列表中的行數為偶數時才運行),我收到一個TypeError。
Traceback (most recent call last):
File "C:\Users\METC\Dropbox\assassins.py", line 150, in <module>
main()
File "C:\Users\METC\Dropbox\assassins.py", line 11, in main
update(ops, pList)
File "C:\Users\METC\Dropbox\assassins.py", line 125, in update
b = match(pList)
File "C:\Users\METC\Dropbox\assassins.py", line 47, in match
q, p = 0
TypeError: 'int' object is not iterable
任何幫助將不勝感激,但請記住,我是該語言的初學者,所以請保持柔和。 :)我不介意您是否技術過高; 我有計算機科學的經驗。
def match(pList):
b = []
z = len(pList)-1
for x in range(z):
b.append([pList[x][0],0])
for x in range(z):
isValid = False
q, p = 0
while isValid == False:
q = random.randint(0, z)
print('q is ' + str(q))
if q > z:
isValid = False
elif q < 0:
isValid = False
elif pList[q][1] == True:
isValid = False
else:
isValid = True
isMatch = False
while isMatch == False:
if pList[q][1] == False:
isValid = False
while isValid == False:
p = random.randint(0,z)
print('p is ' + str(p))
if p > z:
isValid = False
elif p < 0:
isValid = False
elif pList[p][2] == True:
isValid = False
else:
if q == p:
isValid = False
else:
isValid = True
print('match valid')
b[q][1] = pList[p][0]
isMatch = True
print('')
return b
這是你的構造:
q, p = 0
它試圖通過迭代來解壓縮單個int。 那不是有效的Python語法。 我想錯誤可能會更好。
采用:
q = p = 0
代替。
您已經使邏輯變得非常復雜,以至於我將不得不進行多次遍歷以減小其尺寸並向您展示您在做錯什么。
首先,如其他人所述,我們將修復實際報告的錯誤。 同時,我們將應用一個簡單的原理: 不要與布爾文字進行比較 。 您不會說“如果確實在下雨,我將需要一把雨傘”。 您說“如果正在下雨,我需要一把雨傘”。 所以切掉多余的東西。 if isValid
比if isValid == True
更清晰,因為它准確地突出了isValid
含義。 我還將去掉調試跟蹤( print
語句顯然僅用於檢查代碼是否做對了; 首先簡化代碼 ,然后減少檢查的范圍)。
def match(pList):
b = []
z = len(pList)-1
for x in range(z):
b.append([pList[x][0],0])
for x in range(z):
isValid = False
q = p = 0
while not isValid:
q = random.randint(0, z)
if q > z:
isValid = False
elif q < 0:
isValid = False
elif pList[q][1]:
isValid = False
else:
isValid = True
isMatch = False
while not isMatch:
if not pList[q][1]:
isValid = False
while not isValid:
p = random.randint(0,z)
if p > z:
isValid = False
elif p < 0:
isValid = False
elif pList[p][2]:
isValid = False
else:
if q == p:
isValid = False
else:
isValid = True
b[q][1] = pList[p][0]
isMatch = True
return b
接下來,我們將簡化條件邏輯。 首先,從random.randint(0, z)
返回的結果永遠不能為< 0
或> z
,無論如何。 這就是功能的關鍵所在。 因此,編寫代碼來處理這些情況毫無意義,實際上這樣做是錯誤的。 編寫代碼來處理某些事情意味着它實際上可能發生。 對於閱讀代碼的人來說,這是一種分心的事情,而且是在說謊。 它在重要的事情之間(對random.randint
的調用和對pList
值的檢查)之間pList
額外的空間。
我們還將簡化if / else對,它們僅相應地設置了另一個布爾值。 出於同樣的原因,您不會寫
if x == 1:
y == 1
elif x == 2:
y == 2
# ... etc. ad infinitum for every possible integer value of x
您也不應該對布爾值做同樣的事情。 最后,我們可以並且應該使用邏輯and
和or
連接布爾條件。
def match(pList):
b = []
z = len(pList)-1
for x in range(z):
b.append([pList[x][0],0])
for x in range(z):
isValid = False
q = p = 0
while not isValid:
q = random.randint(0, z)
isValid = not pList[q][1]
isMatch = False
while not isMatch:
if not pList[q][1]:
isValid = False
while not isValid:
p = random.randint(0,z)
isValid = not pList[p][2] and (q != p)
b[q][1] = pList[p][0]
isMatch = True
return b
我的下一步將是修復列表索引。 索引到列表通常不是您真正想要的 ,實際上,這里引入了一個錯誤。 顯然,您要遍歷pList
每個“行”; 但是range(z)
會為您提供從0
到z-1
含range(z)
數字,因此在計算z
從len(pList)
中減去1是不正確的。 例如,如果pList
有5個元素,則將計算z = 4
,並產生range(z) = [0, 1, 2, 3]
。 您將永遠不會訪問pList[4]
,並且b
將只有4個元素。
從根本上講,您正在使用z
做兩件事。 一種是使循環運行的次數與pList
中“行”的pList
,並且(在第一個循環中)對每個“行”執行某項操作。 去做這個
這非常重要: range
不是魔術,並且它與for循環沒有特殊聯系 。 它只是一個產生數字列表的函數。 在Python中, for
循環直接為您提供元素 。 所有這些對索引的廢話就是廢話,最好留給能力較弱的語言使用。 如果要對列表的每個元素進行操作 ,請通過編寫遍歷列表的每個元素的代碼對列表的每個元素進行操作 。 直。 不要超過一些單獨的索引列表,然后使用這些索引重新索引到原始索引。 這使事情變得復雜。
使用z
的第二件事是生成一個可能的索引隨機數,以便您可以索引pList
以獲得隨機行。 換句話說,您只想選擇一個隨機行。 因此, 只需選擇一個隨機行 。 random
模塊直接提供了此功能:該函數稱為random.choice
,它的功能完全像聽起來的那樣。
這里有一個小障礙:原始代碼比較p == q
,即比較兩個隨機選擇的列表索引是否相等。 如果我們不再編制索引,那么就沒有索引可比較了。 要解決此問題,我們需要了解最初的目的是: 檢查新選擇的行是否實際上又是舊選擇的行 。 再次,我們通過直接檢查來簡化:我們選擇新行而不是新索引,然后查看它is
為舊索引。
還有一個問題是,我們需要從b
中選擇一個對應的行,該行對應於pList
我們先前將其標識為q
任何行。 為了解決這個問題,我們可以在選擇pList
行的同時選擇b
行。 這有點棘手:我的方法是制作成對的行列表-在每對中,從b
開始一行,然后從pList
一行。 這不需要任何復雜的操作-實際上,有一個內置函數可以將b
和pList
完全按照我們的意願縫合在一起:它稱為zip
。 無論如何,已經從該行對列表中選擇了一個行對,我們只需要將兩行解壓縮為兩個變量-首先使用錯誤的q, p = ...
語法即可,因為原來。 那就是它的目的。
通過這些更改,我們實際上可以完全擺脫p
, q
和z
。 很好,因為無論如何這些名字到底意味着什么還不清楚。
def match(pList):
b = []
for row in pList:
b.append([row[0], 0])
for row in pList:
isValid = False
while not isValid:
first_row, b_row = random.choice(zip(pList, b))
isValid = not first_row[1]
isMatch = False
while not isMatch:
if not first_row[1]:
isValid = False
while not isValid:
second_row = random.choice(pList)
isValid = not second_row[2] and (first_row is not second_row)
b_row[1] = second_row[0]
isMatch = True
return b
是時候進行一些更合理的清理了。 在第一個while循環中,我們將繼續循環直到isValid
變為true。 也就是說,直到not first_row[1]
變為true為止。 在第二個while循環中, first_row
從未更改,因此,由於在循環開始時not first_row[1]
為true,因此在整個過程中它將保持為true。 因此,完全不需要if-check。
一旦結束,我們發現第二個while循環實際上也完全沒有用:它將while not isMatch
之前循環, 直到 isMatch
為止 。 什么是isMatch
? 好吧,在我們開始循環之前,它是False
,而在循環結束時它是True
。 總是。 因此,我們知道這段代碼將只運行一次。 我們進入循環,到最后,將isMatch
設置為true,然后退出,因為剛剛設置為true的isMatch
為true。 只運行一次的代碼不需要循環; 這只是代碼。
我在這里要做的另一件事是,將while isValid
循環稍微轉換一下,以將其轉換為結束while isValid
開始break
。 break
不是邪惡的 (也不是continue
)。 它們實際上簡化了我們對布爾值的思考,因為我們不再檢查not isValid
(強調not
); 我們只是直接與分配給isValid
進行比較。 這也意味着我們也擺脫了isValid
變量,這再次是一個實際上並不能告訴我們太多的名稱 。
def match(pList):
b = []
for row in pList:
b.append([row[0], 0])
for row in pList:
while True:
first_row, b_row = random.choice(zip(pList, b))
if not first_row[1]:
break
while True:
second_row = random.choice(pList)
if not second_row[2] and (first_row is not second_row):
break
b_row[1] = second_row[0]
return b
最后一件事:我們可以更清晰地構造b
。 通過添加元素來構建列表是一個傻瓜游戲。 不要告訴Python如何建立清單。 它知道如何。 而是要求提供符合您要求的清單 ,並具有清單理解力 。 顯示的內容比解釋的更簡單(如果您需要解釋,請咨詢Google),所以我將繼續為您提供一個版本:
def match(pList):
b = [[row[0], 0] for row in pList]
for row in pList:
while True:
first_row, b_row = random.choice(zip(pList, b))
if not first_row[1]:
break
while True:
second_row = random.choice(pList)
if not second_row[2] and (first_row is not second_row):
break
b_row[1] = second_row[0]
return b
從現在開始,如果不了解您實際在做什么 ,就很難糾正或改進任何東西。 完成所有這些工作后, 我仍然不知道!
設置方式的選擇是,選擇一個隨機的行,其數量與行數相同,但是您仍然可以選擇重復的行。 那是你真正想要的嗎? 還是要以隨機順序選擇每一行一次? 無論如何,以隨機順序進行操作有什么意義?
選擇第一行之后,選擇一個隨機的第二行進行匹配。 您是否真的想要每第一行隨機出現一行? 還是您想嘗試所有可能的行對?
究竟這些數據到底是什么? 輸出b
數據代表什么? pList
首先是什么,為什么叫pList
? 您與此match
功能“匹配”什么? 老實說,我無法想象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.