我必须在Python中反转一个列表,我知道方法reverse()可以正常工作。 但是,我偶然发现了这段代码也完成了这项工作,但我无法理解它。
这是返回列表的函数。
def reverse(list):
for i in range(len(list) // 2):
list[i], list[len(list) -i -1] = list[len(list) -i -1], list[i]
return list
为什么循环在这里经过列表长度的一半?而且,我不理解第三行中的两个逗号。
答案 0 :(得分:6)
def reverse(list):
for i in range(len(list) // 2):
print('Swapping {} and {}'.format(i, len(list) -i -1))
# list[i], list[len(list) -i -1] = list[len(list) -i -1], list[i]
return list
reverse(range(9))
产量
Swapping 0 and 8
Swapping 1 and 7
Swapping 2 and 6
Swapping 3 and 5
这应该让你知道代码在做什么。
有助于了解
a, b = b, a
交换变量a
和b
中的值。在作业Python evaluates the right-hand side of the assignment first中。然后将值分配给左侧的变量。
所以
list[i], list[len(list) -i -1] = list[len(list) -i -1], list[i]
正在交换列表中i
和len(list)-i-1
索引位置的值。
顺便说一下,命名变量list
是不好的,因为它会影响同名的Python内置。
答案 1 :(得分:3)
它只会循环列表长度的一半,但对于每个循环,它会移动列表中的两个对象。它使用元组打包/解包来在一行代码中交换两个值。第三行主要是说a, b = b, a
,它会从b
和a
创建一个元组,然后将第一个成员分配给a
,将第二个成员分配给b
。最终结果是a
和b
交换值,而不必使用3行代码和临时变量。
答案 2 :(得分:2)
如果右手大小返回多个内容,您可以在语句的左侧分配多个元素。它可能也写得像:
list[i] = list[len(list)-i-1]
list[len(list)-i-1] = list[i]
但是上面会以原子方式执行。顺便说一下,上面什么都不做,因为它需要一个临时变量,因此单行是一个很好的捷径。
逻辑上,这是一个交换。要反转列表,只需将元素与其镜像相对于数组的中间交换,因此仅循环到len(list)/2
答案 3 :(得分:2)
你只需要浏览一半的列表,因为每次通过你交换两个项目,从第一个和最后一个开始,然后是第二个和倒数第二个,依此类推。所以一旦你到达列表中的中间项目,你就完成了。如果你继续前进,你会撤消你刚刚做的所有事情,将每个项目交换回来。
对于带逗号的行,它基本上只是一次执行多个赋值的快捷方式,但附加的好处是分配是同时执行而不是顺序执行,这意味着:
a, b = b+1, a+1
会产生新值a_new = b_old + 1
和b_new = a_old + 1
,而操作如下:
a = b+1
b = a+1
会产生值a_new = b_old + 1
和b_new = a_new + 1
。在前一种情况下,两个语句在赋值之前进行计算,而在后一种情况下,每一行都是按顺序计算的,因此a
的值在我们使用它来更新b
的值之前会更改
对于交换算法,您希望确保同时(并发)而不是按顺序切换两个值。如果你考虑第一个和最后一个值,这是显而易见的。通过同时交换,我们得到first_new = last_old
和last_new = first_old
。如果我们按顺序交换,我们会有first_new = last_old
和last_new = first_new = last_old
,所以我们的交换不起作用。
修改:Python Tutorial where they use this notation can be found here中的示例。
答案 4 :(得分:1)
这只会通过列表的一半,因为它同时在两端运行。在这种情况下,逗号运算符允许您分配多个变量,并且工作方式如下:
a,b = b,a # now a has b's value and b has a's value
这就是他们在那里做的事情,所以实际上函数从第一个和最后一个元素开始,交换它们,然后转到第二个和倒数第二个元素,依此类推,直到没有什么可以交换