Python: copying a list the right way

90% of the time [:] could be replaced by list(). Of course it won’t work for everything since the two are not strictly equivalent, but it is worth trying. Next time you see a [:] try to replace it with list, your code should be more readable. Do it, the devil is in the details.

I would use b = [element for element in a] instead. Using b = list(a) is not explicit enough for me when a is already a list -- it's quite confusing. My options is more explicit in that we're creating a list from the elements of a, whatever a is.

6 responses
Please, elaborate further: "my option is more explicit in that we're creating a list from the elements of a, whatever a is".
I mean, list function takes any iterator - lists, tuples, generators or arbitrary classes who implements iteration behavior - and make a list of it's elements.
It's subtle... I think my point was that if you do:

b = list(a)

You're saying "convert 'a' to a list and give it the label 'b'". But if 'a' is already a list (as was the case), it's kind of awkward -- why would you convert a list if it's already a list?

When you do:

b = [el for el in a]

You're saying "hey, create this list 'b', using the elements from a". If 'a' is already a list, be it.

The point is, I think of 'list' as an analogous of 'float' or 'str'. It's like making a copy of a string (if it was necessary), using:

b = str('this is my string')

To wrap it all after a coffee: for me, list() is for type conversion, and a list comprehension is a way of creating list. So, to create a new list I'd rather use the later.
It should be "[..] and make a list of *its* elements."
I agree list() is for type conversion just like str, int; although, I read it like: make a list of the elements of this generator|list|tuple passed as parameter. Similarly, int() is read as: make an integer from the parameter given. So I'm fine with it.
Researching further, the list comprehension produces more verbose bytecode since it has to setup a For iterator. List comprehensions in Python are very optimized and more bytecode alone shouldn't mean poorer performance so I wrote a poor's man benchmark which suggests list() implementation is faster than the list comprehension.

list_comprehension.py
my_list = list(range(1000000))

for i in range(100):
other_list = [elem for elem in my_list]

list_function.py
my_list = list(range(1000000))

for i in range(100):
other_list = list(my_list)

$ time python list_comprehension.py
real 0m17.746s
user 0m14.489s
sys 0m1.827s

$ time python list_function.py
real 0m4.266s
user 0m3.740s
sys 0m0.319s

Jeez, this comment system just ate my indentation and blank lines. Created a gist: https://gist.github.com/1362759