Byte Commander
Byte Commander

Reputation: 6776

Python: converting iterable to list: 'list(x)' vs. full slice 'x[:]'

I wonder if there is any difference in these two ways to convert an iterable to a list in Python:

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

Answers (3)

John Zwinck
John Zwinck

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

Alex Hall
Alex Hall

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

Padraic Cunningham
Padraic Cunningham

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

Related Questions