在迭代列表时编辑列表(pythonic方式!)

在迭代列表时编辑列表(pythonic方式!),python,list,Python,List,所以,我知道如何做到这一点,但它似乎不太适合我。有没有更干净的方法 arr = list(range(10)) print(arr) for n in range(len(arr)): # Perform som operation on the element that changes the value "in place" arr[n] += 1 print(arr) 输出(这是我想要的): 您可以使用: 这将产生一个新的列表;在上面的示例中,我将结果反弹到相同的名称 如

所以,我知道如何做到这一点,但它似乎不太适合我。有没有更干净的方法

arr = list(range(10))
print(arr)
for n in range(len(arr)):
    # Perform som operation on the element that changes the value "in place"
    arr[n] += 1
print(arr)
输出(这是我想要的):

您可以使用:

这将产生一个新的列表;在上面的示例中,我将结果反弹到相同的名称

如果您对列表有多个引用,并且需要对其进行适当的更改(以便其他引用可以看到更改),请指定给标识片(
[:]
),以更新列表的所有索引,而不是重新绑定名称:

arr[:] = [i + 1 for i in arr]
这将首先创建一个新的list对象,然后Python足够聪明,可以看到两个列表的大小相同,并且在再次释放第二个列表之前只在元素之间进行复制

在这种情况下,您甚至可以使用生成器表达式来避免创建额外的列表:

arr[:] = (i + 1 for i in arr)

这会将原始元素移到一边,为新元素腾出空间,但不会为此创建新的Python列表对象。这应该会更节省内存。

使用列表理解:

arr = [x + 1 for x in arr]

他们所说的。但是,如果要在创建列表时执行此操作,可以执行以下操作:

arr = [u + 1 for u in range(10)]
我猜您使用的是Python 3。如果您使用的是Python 2,那么将
range
更改为
xrange
(除非列表大小非常小),因为Python 2
range
函数返回一个实际的
list
,但
xrange
返回一个迭代器;python3
range
函数返回的迭代器与旧的
xrange
类似(但有一些改进)

如果
arr
是要修改的现有
列表
,而不使用新的
列表
对象替换当前的
列表
对象,则可以执行以下操作:

arr[:] = [u + 1 for u in arr]

下面的一些代码说明了在作业左侧使用
arr
arr[:]
之间的区别

arr = list(range(10))
b = arr
print(id(arr), id(b))
arr = [u + 1 for u in arr]
print(id(arr), id(b))
print(arr, b)

c = arr
print(id(arr), id(c))
arr[:] = [u + 1 for u in arr]
print(id(arr), id(c))
print(arr, c)
输出

3073636268 3073636268
3073629964 3073636268
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3073629964 3073629964
3073629964 3073629964
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

因此
arr=[u+1表示arr中的u]
将名称
arr
绑定到一个新的列表对象,但是
arr[:]=[u+1表示arr中的u]
有效地改变了现有的列表对象。“引擎盖下”它创建一个新的临时列表对象,然后将其内容复制到旧的列表对象。

真是太棒了!因为我实际上是用micropython实现的,所以我不想创建一个新的列表(它已经占用了我的内存!),所以我可能会坚持使用就地解决方案…@Clausen:在内存受限的环境中,您应该使用一个生成器表达式。@Clausen:很高兴您发现不止一个答案很有用!不幸的是,您可以将“已接受”分数授予此处的一个答案。选择你觉得最有用的一个(如果你不能选择,也可以不选一个)。那么后者是有效的吗?@Clausen:嗯,它实际上比只做
arr=[u+1表示arr中的u]
要慢一点,但除非列表很大,否则你不会注意到速度的差异。但是使用
arr[:]=
的主要优点是,如果您有多个对
arr
的引用,那么它们将保持有效,正如Martijn在他的回答中所解释的那样。如果只使用
arr=
,那么这些其他引用仍将指向旧数据,而不是更新的数据。
arr = list(range(10))
b = arr
print(id(arr), id(b))
arr = [u + 1 for u in arr]
print(id(arr), id(b))
print(arr, b)

c = arr
print(id(arr), id(c))
arr[:] = [u + 1 for u in arr]
print(id(arr), id(c))
print(arr, c)
3073636268 3073636268
3073629964 3073636268
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3073629964 3073629964
3073629964 3073629964
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]