列表理解和就地方法

List comprehension and in place methods

我只是想了解在列表理解过程中发生了什么。某些适用于列表 'in-place' 的方法在应用于列表理解时似乎不起作用:

a = [[1, 2, 3], [4, 5, 6]]
i1 = id(a[0])

for i in a: i.reverse()
>>> [[3, 2, 1], [6, 5, 4]  # Works
print i1 == id(a[0])  # True, same memory address

a = [i.reverse() for i in a]
>>> [None, None]  # Doesn't work
print i1 == id(a[0])  # False, new memory address

a = [i[::-1] for i in a]
>>> [[3, 2, 1], [6, 5, 4]]  # Works!
print i1 == id(a[0])  # False

我猜这与所有元素都被复制到不同的内存有关space。为什么 i[::-1] 有效而 i.reverse() 无效?

i.reverse() 就地反转数组并且不 return 任何东西,这意味着它是 returns None 类型。这样你就可以从列表理解中获得 [None, None] 并且先前数组的元素同时被反转。

这两个不应该混用,要么使用 forx.reverse(),要么在列表理解中使用 reversed(x)x[::-1]

i.reverse() 就地反转列表并且 returns None.

文档怎么说:

list.reverse()

Reverse the elements of the list, in place

对比

reversed(seq)

Return a reverse iterator. seq must be an object which has a __reversed__() method or supports the sequence protocol (the __len__() method and the __getitem__() method with integer arguments starting at 0).

示例:

>>> xs = [1, 2, 3]
>>> id(xs)
140625121860208
>>> ys = xs[::-1]
>>> id(ys)
140625121924088

切片创建一个新列表。

>>> xs.reverse()
>>> xs
[3, 2, 1]
>>> id(xs)
140625121860208

就地 sorting/reversing 保留原始列表。

>>> zs = list(reversed(xs))
>>> zs
[1, 2, 3]
>>> id(zs)
140625121976400

reversed() returns 一个迭代器;当变成一个列表时,它会创建一个新列表!如果您读过 PEP 0322 -- Reverse Iteration,您会注意到 reversed() 不会创建新的数据结构,而只是以相反的顺序迭代序列。

这就是你想要的:

>>> a = [[1, 2, 3], [4, 5, 6]]
>>> [list(reversed(i)) for i in a]
[[3, 2, 1], [6, 5, 4]]

列表理解总是 return 一个新列表,所以使用就地 reverse 方法只是 returns reverse 的 return 值,即 None.

函数reversed() 为您提供了一个新的迭代器。将其转换为 对于您的示例,列表与以下内容相同:

>>> [i[::-1] for i in a] 

尽管它们看起来非常相似,但区分两者很重要, 函数 reversed() 和方法 obj.reverse()

list.reverse 原地反转列表,return None。 而 slice a[::-1] 创建另一个列表并 return 作为值。

列表理解将采用每个表达式的 return value