问题描述
我试图返回一个数字列表的两个最小值作为元组。 但是,下一个代码将继续返回列表的前两个值。
def test():
list = [4,5,1,9,-2,3,-5]
min1 = list[0]
min2 = list[1]
length = len(list)
for i in range(1,length):
if list[i] < list[0]:
if list[0] < list[1]:
list[i] = list[1]
else:
list[i] = list[1]
else:
if list[i] < list[1]:
list[i] = list[1]
print(min1,min2)
return (min1,min2)
test()
控制台输出:
4,5
有没有办法通过迭代来做到这一点?
解决方法
变量min1
和min2
不会更新,它们不是对列表的第一个和第二个元素的引用,它们是对索引0和1处的值的引用任务何时发生。以后更改list[0]
和list[1]
没关系。
在Python中,列表索引和变量都只是对实际对象的引用。想想像气球这样的Python对象,变量和索引只是与附加到气球上的字符串相关的标签。您可以在气球上附加多个标签,但是如果要将标签移动到另一个气球上,则与旧气球绑在一起的 other 标签不会随之出现。
在这里,min1
和min2
被绑定到已经具有0
和1
索引标签的气球上。稍后,当您分配给list[i]
时,您将特定的索引标签退休了另一个气球,但是min1
和min2
标签没有改变。
请注意,代码的这一部分有一个相当明显的错误:
if list[0] < list[1]:
list[i] = list[1]
else:
list[i] = list[1]
两个分支都做同样的事情,将list[1]
分配给list[i]
。
否则,即使您希望在循环中更改list[0]
和list[1]
也会更改min1
和min2
的值,否则您所做的分配是完全错误的,您正在更改列表中的 other 值list[i]
,该值应该较小。
因此对于i = 2
,list[i]
是list[2]
,而list[2] < list[0]
是真实的(1 list[0] < list[1]是否也是真实的(4 list[i] = list[1],设置list[2] = 5
,将list[0]
设置为4
,将list[1]
设置为5
,并生效丢弃之前在1
处出现的list[2]
值。
让您的循环更新list[0]
和list[1]
而不是与min1
或min2
进行比较:
# min1 is always smaller than min2
min1,min2 = list[:2]
if min2 < min1:
min1,min2 = min2,min1
for i in range(1,length):
if list[i] < min1:
min1 = list[i]
elif list[i] < min2: # but equal to or greater than min1!
min2 = list[i]
我还确保开始时使用min1 < min2
,这使循环变得更加简单,因为如果list[i] < min1
不正确,则它可能可能小于{{ 1}},但您无需再次测试min2
。
请注意,我们在这里将min1
的值分配给list[i]
和min1
,您要使用刚刚测试的值更新这两个变量, min2
确实比以前小。