Reputation: 6776
I wonder if there is any difference in these two ways to convert an iterable to a list in Python:
using the list()
constructor:
my_list = list(my_iterable)
using a full slice:
my_list = my_iterable[:]
Are there differences in the implementation? If so, what about performance? Any changes in Python 2 vs. Python 3?
Of course I realize that the constructor version is much better readable though.
Upvotes: 3
Views: 2487
Reputation: 249592
list(thing)
gives you a list.
thing[:]
could give you any type it wants.
In other words, the second option only works with specific types (and you haven't mentioned which types you're actually working with).
Edit: A useful feature of thing[:]
is that when it is supported it usually results in a reference to "all the elements of the thing" which can be modified without changing which object thing
points to. For example:
thing[:] = [1,2,3]
Will assign [1,2,3]
over top of whatever was in thing
, even if that's not a list per se. Whereas:
list(thing) = [1,2,3]
Is nonsense, and:
thing = [1,2,3]
Makes thing
refer to a new list, regardless of its previous type.
Upvotes: 10
Reputation: 36043
Not everything supports slicing, e.g. generators:
(x for x in range(5))[:] # raises an error
So list
is more general. [:]
is a mostly just a way to copy a list.
The main reason [:]
is possible is because it's what you get when you combine leaving out the index before the colon (e.g. [:3]
) and leaving out the index after, both of which are useful by themselves. It's also useful if you add a step, e.g. [::-1]
is a common way to reverse a string. [:]
is not very useful by itself for a list but it is slightly faster for certain situations as I've commented on Padriac's answer, although readability is usually more important than such micro-optimisations.
For non-lists, [:]
could theoretically do anything depending on what you tell it to:
class A(object):
def __getitem__(self, item):
return 3
print A()[:] # prints 3
But you should probably avoid such definitions.
Upvotes: 10
Reputation: 180532
I presume my_iterable is always a list or a subclass of list or both methods could produce completely different results:
In python2 calling list is slightly faster than slicing:
In [2]: l = list(range(1000000))
In [3]: timeit l[:]
100 loops, best of 3: 10.8 ms per loop
In [4]: timeit list(l)
100 loops, best of 3: 9.45 ms per loop
Python3 has very similar results:
In [1]: l = list(range(1000000))
In [2]: timeit list(l)
100 loops, best of 3: 9.54 ms per loop
In [3]: timeit l[:]
100 loops, best of 3: 10.6 ms per loop
[:]
is used to slice all the elements from anything that supports slicing, trying to compare calling list
or using [:]
outside of when my_iterable
is a list makes no real sense as they both do very different things based on what you use them on.
In [2]: i = (1,2,3,4,5)
In [3]: list(i)
Out[3]: [1, 2, 3, 4, 5]
In [4]: i[:]
Out[4]: (1, 2, 3, 4, 5)
In [5]: i = "hello world"
In [6]: list(i)
Out[6]: ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
In [7]: i[:]
Out[7]: 'hello world'
Upvotes: 1