[英]Python throws ValueError: list.remove(x): x not in list (not iterating over list)
[英]Python throws ValueError: list.remove(x): x not in list
每次我運行這個程序,我都會得到這個錯誤:
ValueError: list.remove(x): x not in list
每當被螺栓擊中時,我都試圖降低單個外星人的健康狀況。 如果那個外星人的健康狀況<= 0
,它也應該被摧毀。 同樣,螺栓也將被破壞。 這是我的代碼:
def manage_collide(bolts, aliens):
# Check if a bolt collides with any alien(s)
for b in bolts:
for a in aliens:
if b['rect'].colliderect(a['rect']):
for a in aliens:
a['health'] -= 1
bolts.remove(b)
if a['health'] == 0:
aliens.remove(a)
# Return bolts, aliens dictionaries
return bolts, aliens
ValueError
發生在aliens.remove(a)
行。 澄清一下, aliens
和bolts
都是字典列表。
我究竟做錯了什么?
你不應該從你正在循環的列表中刪除項目。 改為創建副本:
for a in aliens[:]:
和
for b in bolts[:]:
在循環時修改列表會影響循環:
>>> lst = [1, 2, 3]
>>> for i in lst:
... print i
... lst.remove(i)
...
1
3
>>> lst
[2]
從您循環兩次的列表中刪除項目會使事情變得更加復雜,從而導致 ValueError:
>>> lst = [1, 2, 3]
>>> for i in lst:
... for a in lst:
... print i, a, lst
... lst.remove(i)
...
1 1 [1, 2, 3]
1 3 [2, 3]
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ValueError: list.remove(x): x not in list
在創建您在循環的每個級別修改的列表的副本時,您可以避免這個問題:
>>> lst = [1, 2, 3]
>>> for i in lst[:]:
... for i in lst[:]:
... print i, lst
... lst.remove(i)
...
1 [1, 2, 3]
2 [2, 3]
3 [3]
當你發生碰撞時,你只需要移除b
螺栓一次,而不是在你傷害外星人的循環中。 稍后單獨清理外星人:
def manage_collide(bolts, aliens):
for b in bolts[:]:
for a in aliens:
if b['rect'].colliderect(a['rect']) and a['health'] > 0:
bolts.remove(b)
for a in aliens:
a['health'] -= 1
for a in aliens[:]:
if a['health'] <= 0:
aliens.remove(a)
return bolts, aliens
您的代碼中存在導致此問題的錯誤。 您的代碼經過簡化,如下所示:
for b in bolts:
for a in aliens:
for a in aliens:
bolts.remove(b)
這導致您為b
每個條目多次循環aliens
。 如果 b 在aliens
的第一次循環中被刪除,那么當它第二次循環時,你會得到那里的錯誤。
一些事情要解決。 首先,改變aliens
的內部循環以使用a
以外a
東西,所以:
for b in bolts:
for a in aliens:
for c in aliens:
if hit:
bolts.remove(b)
其次,只從bolts
取下b
一次。 所以:
for b in bolts:
for a in aliens:
should_remove = False
for c in aliens:
if hit:
should_remove = True
if should_remove:
bolts.remove(b)
我認為此代碼還有其他問題,但這是導致您的主要問題的原因。 Martijn 的帖子也可能有所幫助。
你不能使用 list.remove 你應該使用 del list[x]
因為當你使用remove時你必須按名稱而不是索引來命名被刪除的項目,所以當代碼操作時會出現這個錯誤(值錯誤:x不在列表中)但是當我們使用del時就可以了,因為我們刪除項目它的索引。 無論項目的名稱是什么,使用del,代碼都會正確運行我希望我清除了問題並解決了它
要確切地知道我的意思,請嘗試此代碼然后通過用刪除重新調整 del 來嘗試它,您就會知道我的意思。 代碼如下:
aliens = [[4,3,2,1],[4,3,2,1],[4,3,2,1]]
print(aliens)
bolts = [b for b in range(1,30)]
for b in bolts:
del aliens[0][0]
print(aliens)
if len(aliens[0]) == 0:
del aliens[0]
if len(aliens) == 0
print("you win")
break
也給螺栓一個“健康”,初始化為 1。然后你可以做一個嵌套循環來計算所有的傷害,和兩個單獨的非嵌套“循環”來刪除所有“死”的東西。 除了,不要那樣做,因為您仍然不想修改您正在循環的列表。 制作副本還是太復雜了。 您真正想要做的是直接構建一個僅包含仍然“活着”的事物的新列表,您可以使用列表推導式(或如此處所示,使用filter
)進行描述性的完成。
# for example
class Alien:
# ... other stuff
def damage(self): self.hp -= 1
def alive(self): return self.hp > 0
# similarly for Bolt
def collide(an_alien, a_bolt):
# etc.
def handle_collisions(aliens, bolts):
for a in aliens:
for b in bolts:
if collide(a, b):
a.damage()
b.damage()
return list(filter(Alien.alive, aliens)), list(filter(Bolt.alive, bolts))
我認為如果你用 while 循環替換 for 循環 - 只有在你從列表中刪除的循環中 - 將解決它
像這樣
lis = [1,2,3,4,5,6]
i=0
while i in range(len(lis)) :
lis. remove(lis[i])
我推薦這個:
def manage_collide(bolts, aliens):
# Check if a bolt collides with any alien(s)
for b in bolts[:]:
for a in aliens[:]:
if b['rect'].colliderect(a['rect']):
a['health'] -= 1
bolts.remove(b)
if a['health'] == 0:
aliens.remove(a)
# Return bolts, aliens dictionaries
return bolts, aliens
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.