如何在 python 的列表中使用切片运算符避免 for 循环中的副作用?
How to avoid side effect in for loop using slicing operator in a list in python?
这是引用自 link : 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"]
是如何附加到原始颜色列表的?
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")
语句colours[:]
是否复制颜色列表:是。
并且 for 循环适用于副本而不是原始列表? 是的,但请注意 "works on" 的意思。变量 i
从列表 colours
的副本中获取其值。但是,对 colours
的引用(例如 colours += ["black"]
行中的引用)指的是原始列表。这正是代码想要的,所以它有效。
如果是这样,那么["balck"]是如何追加到原来的颜色列表中的?这是因为追加的那一行是指原始列表而不是列表的副本。
这是您在 link 中引用的代码:
如果循环列表,最好避免在循环体中更改列表。举个例子,看看会发生什么,看看下面的例子:
colours = ["red"]
for i in colours:
if i == "red":
colours += ["black"]
if i == "black":
colours += ["white"]
print colours
"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",但我们的更改对循环没有任何影响了。要循环的元素在迭代期间保持不变。
所以:
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)
这是引用自 link : 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"]
是如何附加到原始颜色列表的?
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")
语句colours[:]
是否复制颜色列表:是。
并且 for 循环适用于副本而不是原始列表? 是的,但请注意 "works on" 的意思。变量 i
从列表 colours
的副本中获取其值。但是,对 colours
的引用(例如 colours += ["black"]
行中的引用)指的是原始列表。这正是代码想要的,所以它有效。
如果是这样,那么["balck"]是如何追加到原来的颜色列表中的?这是因为追加的那一行是指原始列表而不是列表的副本。
这是您在 link 中引用的代码:
如果循环列表,最好避免在循环体中更改列表。举个例子,看看会发生什么,看看下面的例子:
colours = ["red"]
for i in colours:
if i == "red":
colours += ["black"]
if i == "black":
colours += ["white"]
print colours
"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",但我们的更改对循环没有任何影响了。要循环的元素在迭代期间保持不变。
所以:
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)