现在我知道在迭代循环期间修改列表是不安全的。但是,假设我有一个字符串列表,我想剥离字符串本身。替换可变值算作修改吗?
相关问题请参见for循环中python变量的作用域:给迭代变量赋值不会修改底层序列,也不会影响未来的迭代。
现在我知道在迭代循环期间修改列表是不安全的。但是,假设我有一个字符串列表,我想剥离字符串本身。替换可变值算作修改吗?
相关问题请参见for循环中python变量的作用域:给迭代变量赋值不会修改底层序列,也不会影响未来的迭代。
当前回答
Ignacio Vazquez-Abrams给出的答案非常好。这个例子可以进一步说明。想象一下:
给出了一个包含两个向量的列表。 您希望遍历列表并反转每个数组的顺序。
假设你有:
v = np.array([1,2,3,4])
b = np.array([3,4,6])
for i in [v, b]:
i = i[::-1] # This command does not reverse the string.
print([v,b])
你会得到:
[array([1, 2, 3, 4]), array([3, 4, 6])]
另一方面,如果你这样做:
v = np.array([1,2,3,4])
b = np.array([3,4,6])
for i in [v, b]:
i[:] = i[::-1] # This command reverses the string.
print([v,b])
结果是:
[array([4, 3, 2, 1]), array([6, 4, 3])]
其他回答
多一个for循环变量,对我来说看起来比使用enumerate()更干净:
for idx in range(len(list)):
list[idx]=... # set a new value
# some other code which doesn't let you use a list comprehension
因为下面的循环只修改了已经看到的元素,所以它被认为是可以接受的:
a = ['a',' b', 'c ', ' d ']
for i, s in enumerate(a):
a[i] = s.strip()
print(a) # -> ['a', 'b', 'c', 'd']
这不同于:
a[:] = [s.strip() for s in a]
因为它不需要创建一个临时列表,也不需要分配它来替换原来的列表,尽管它确实需要更多的索引操作。
警告:尽管您可以以这种方式修改条目,但您不能在不冒遇到问题的风险的情况下更改列表中条目的数量。
下面是我的意思的一个例子-删除一个条目会从这一点上搞乱索引:
b = ['a', ' b', 'c ', ' d ']
for i, s in enumerate(b):
if s.strip() != b[i]: # leading or trailing whitespace?
del b[i]
print(b) # -> ['a', 'c '] # WRONG!
(结果是错误的,因为它没有删除所有应该删除的项。)
更新
由于这是一个相当流行的答案,下面是如何有效地“就地”删除条目(尽管这并不是问题的关键):
b = ['a',' b', 'c ', ' d ']
b[:] = [entry for entry in b if entry.strip() == entry]
print(b) # -> ['a'] # CORRECT
参见如何在迭代时从列表中删除项?。
这被认为是糟糕的形式。如果需要保留对列表的现有引用,则使用列表理解式,并使用切片赋值。
a = [1, 3, 5]
b = a
a[:] = [x + 2 for x in a]
print(b)
简而言之,在迭代同一列表的同时对列表进行修改。
list[:] = ["Modify the list" for each_element in list "Condition Check"]
例子:
list[:] = [list.remove(each_element) for each_element in list if each_element in ["data1", "data2"]]
我刚刚发现的一些东西-当循环遍历一个可变类型列表(比如字典)时,你可以使用一个正常的for循环,像这样:
l = [{"n": 1}, {"n": 2}]
for d in l:
d["n"] += 1
print(l)
# prints [{"n": 2}, {"n": 1}]