我正在尝试创建一个函数,该函数从子列表中获取随机变量,并在选择后将其删除。但是出于某种原因,当我使用变量定义要删除的内容时,它会从多个子列表中删除,而实际上根本没有从这些子列表中删除任何内容?我不能很好地形容这件事,因为我自己不太了解。这是我为尝试重现该问题而编写的一些代码:
greet = [[1,"Hello!"],[2,"Hi!"], [3,"Howdy!"]]
person = [["John", greet], ["Sally", greet], ["Frank", greet]]
while True:
#This is meant to catch the error random gives when there is an empty list, so it continues if there's an empty list.
#When all lists in person[0][1] and [1][1] and so on and so forth are empty, there is a break function below.
try:
person_select = random.choice(person)
greet_select = random.choice(person_select[1])
person_and_greet_order = [person_select[0], greet_select[1], greet_select[0]]
print(person_and_greet_order)
#This should be activating, but it isn't, leading to an infinite loop
if person[0][1]==[] and person[1][1]==[] and person[2][1]==[]:
print("Everyone greeted!")
break
#Tests to see if greeting was used on person, then remove that greeting from the list so it can't be used again.
elif person_and_greet_order[0]=="John":
person[0][1].remove(greet_select)
print(person)
elif person_and_greet_order[0]=="Sally":
person[1][1].remove(greet_select)
print(person)
elif person_and_greet_order[0]=="Frank":
person[2][1].remove(greet_select)
print(person)
#The else is here to see if it's properly detecting the names.
else:
break
except:
continue
这是您将从中得到的:
[['John', [[2, 'Hi!'], [3, 'Howdy!']]], ['Sally', [[2, 'Hi!'], [3, 'Howdy!']]], ['Frank', [[2, 'Hi!'], [3, 'Howdy!']]]]
['John', 'Hi!', 2]
[['John', [[3, 'Howdy!']]], ['Sally', [[3, 'Howdy!']]], ['Frank', [[3, 'Howdy!']]]]
['Frank', 'Howdy!', 3]
[['John', []], ['Sally', []], ['Frank', []]]
(此后循环到无穷大,因为if语句看不到列表是空的,即使它们是空的?)
如您所见,当我需要从一个子列表中删除一个值时,它会从每个子列表中删除该值,而不是从特定子列表中删除。并且即使空白列表为空,它们也不会注册为空白列表。最终目标是使问候和人的所有可能的组合。我真的是python的新手,我不知道在这里能做什么。我在尽头。有什么建议吗?
答案 0 :(得分:1)
您在greet
中使用了对person
的相同引用,这是错误的,应该做的是在{{1}中使用greet
的副本}列表,而不要使用person
要扩展,像greet[:]
这样的赋值并不会创建一个列表的真实副本,而是最终导致发生的结果是两个变量都指向内存中的同一列表。
因此,更改b = a
中的内容也会反映在a
中
要实际创建副本,我们需要像对b
所做的那样b = a[:]
因此更新后的代码将如下所示
greet[:]
输出将是
import random
greet = [[1,"Hello!"],[2,"Hi!"], [3,"Howdy!"]]
#Use a copy of greet via list slicing
person = [["John", greet[:]], ["Sally", greet[:]], ["Frank", greet[:]]]
while True:
#This is meant to catch the error random gives when there is an empty list, so it continues if there's an empty list.
#When all lists in person[0][1] and [1][1] and so on and so forth are empty, there is a break function below.
try:
person_select = random.choice(person)
greet_select = random.choice(person_select[1])
person_and_greet_order = [person_select[0], greet_select[1], greet_select[0]]
print(person_and_greet_order)
#This should be activating, but it isn't, leading to an infinite loop
if person[0][1]==[] and person[1][1]==[] and person[2][1]==[]:
print("Everyone greeted!")
break
#Tests to see if greeting was used on person, then remove that greeting from the list so it can't be used again.
elif person_and_greet_order[0]=="John":
person[0][1].remove(greet_select)
print(person)
elif person_and_greet_order[0]=="Sally":
person[1][1].remove(greet_select)
print(person)
elif person_and_greet_order[0]=="Frank":
person[2][1].remove(greet_select)
print(person)
#The else is here to see if it's properly detecting the names.
else:
break
except:
continue
答案 1 :(得分:0)
发生这种情况是因为(默认情况下)列表是通过python中的引用复制的。将greet
添加到人员数组时,请尝试将greet
替换为deepcopy(greet)
。这样会在内存中单独创建该列表的副本,因此更改它不会影响您的其他列表。
这需要额外导入from copy import deepcopy