如何在python中的列表中使用切片运算符来避免for循环中的副作用?

时间:2016-10-22 11:05:43

标签: python list python-2.7 slice

引用链接:http://www.python-course.eu/for_loop.php - 为了避免这些副作用,最好使用切片运算符处理副本,如下一个示例所示:

colours = ["red"]
for i in colours[:]:
    if i == "red":
        colours += ["black"]
    if i == "black":
        colours += ["white"]
print colours

输出结果为:

['red', 'black']

我的问题是:语句colours[:]是否复制了颜色列表,for循环是否适用于副本而不是原始列表?如果是这样,那么["balck"]如何附加到原始颜色列表?

3 个答案:

答案 0 :(得分:3)

声明colours[:]是否制作了颜色列表的副本:是。

并且for循环适用于副本而不是原始列表?是的,但请注意“处理”的含义。变量i从列表colours的副本中获取其值。但是,对colours的引用(例如行colours += ["black"]中的引用)是指原始列表。这正是代码所需要的,所以它可以工作。

如果是这样,那么[“balck”]如何附加到原始颜色列表?这是因为执行追加的行是指原始列表而不是副本清单。

答案 1 :(得分:2)

colours[:]制作原始列表的副本并对其进行迭代,但colours仍然是原始列表。以下代码是等效的:

copy = colours.copy()
for i in copy:
    if i == "red":
        colours.append("black")  # append is O(1)
    if i == "black":
        colours.append("white")

答案 2 :(得分:1)

这是您在提供的link中引用的代码:

如果循环遍历列表,最好避免更改循环体中的列表。为了举例说明可能发生的情况,请看下面的示例:

colours = ["red"]
for i in colours:
    if i == "red":
        colours += ["black"]
    if i == "black":
        colours += ["white"]
print colours

“打印颜色”会打印什么?

['red', 'black', 'white']

为避免这些副作用,最好使用切片运算符处理副本,如下一个示例所示

colours = ["red"]
for i in colours[:]:
    if i == "red":
        colours += ["black"]
    if i == "black":
        colours += ["white"]
print colours
Now the output looks like this:
['red', 'black']

我们仍然可能已经做了一些事情,我们不应该做的事情。我们更改了“颜色”列表,但我们的更改对循环没有任何影响。在迭代期间,要循环的元素保持不变。

所以:

colours = ["red"]
for i in colours[:]: # iterates over a copy so we only evaluate what is in the list originally
    if i == "red":
        colours += ["black"]
    if i == "black":
        colours += ["white"]
print(colours) # ["red", "black"]

现在没有副本:

colours = ["red"]
for i in colours:
    if i == "red":
        colours += ["black"] # black gets added, colours -> ["red", "black"]
    if i == "black": # now because of ^^, white gets added.
        colours += ["white"]
print(colours) # -> ['red', 'black', 'white']

现在情况更糟:

colours = ["red"]
for i in colours:
    if i == "red":
        colours += ["red"] # red gets add, colours = ["red", "red"]
                          # 2nd iteration, red gets added, colours ->  colours = ["red", "red", "red"]
                          # infinite loop....
    if i == "black":
        colours += ["white"]
print(colours) 

您正在做的与示例试图显示的内容完全不同,它试图避免将元素添加到您正在迭代的列表中,因此您只评估原始列表中的元素而不是新添加的元素。您正在尝试创建新列表:

colours = ["red"]
new = colours[:] # assign new list/copy to a name.
for i in colours:
    if i == "red":
        new += ["red"] # add to new list
    if i == "black":
        new += ["white"]
print(colours)

您还应该append而不是+=

colours = ["red"]
new = colours[:]
for i in colours:
    if i == "red":
        new.append("red")
    if i == "black":
        new.append("white")
print(colours)