List understanding and apply methods
I'm just trying to figure out what's going on during list comprehension. Some of the methods that work on in-place lists don't seem to work when applied in a list comprehension:
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
I'm guessing it has something to do with all the elements that are copied to another memory space. Why i[::-1]
does it work, but i.reverse()
not?
source to share
i.reverse()
swaps the array in place and returns nothing, which means it returns a type None
. This way you get [None, None]
from the list and the elements of the previous array change at the same time.
The two should not be confused with either use for
and x.reverse()
, or use reversed(x)
or x[::-1]
in the comprehension of the list.
source to share
i.reverse()
cancels the list in place and returns None
.
What docs say:
list.reverse()
Reverse the list items in place
against.
reversed(seq)
Return a reverse iterator. seq must be an object that has
__reversed__()
or supports a sequencing protocol (method__len__()
and method__getitem__()
with integer arguments starting with0
).
<strong> Examples:
>>> xs = [1, 2, 3]
>>> id(xs)
140625121860208
>>> ys = xs[::-1]
>>> id(ys)
140625121924088
Slicing creates a new list.
>>> xs.reverse()
>>> xs
[3, 2, 1]
>>> id(xs)
140625121860208
Sorting / reversing in place keeps the original list.
>>> zs = list(reversed(xs))
>>> zs
[1, 2, 3]
>>> id(zs)
140625121976400
reversed()
returns an iterator; which, when it turns into a list, creates a new list! If you read PEP 0322 - Reverse Iteration , you will notice that it reversed()
does not create a new data structure, but simply iterates the sequence in reverse order.
source to share
This does what you intend:
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> [list(reversed(i)) for i in a]
[[3, 2, 1], [6, 5, 4]]
The List comprehension always returns a new list, so use the reverse
method returns a return value reverse
that is None
.
The function reversed()
gives you a new iterator. Converting it to a list for your example is the same as:
>>> [i[::-1] for i in a]
Although they look very similar, it is important to distinguish between both, function reversed()
and methodobj.reverse()
source to share