quantifiedcode / python-anti-patterns

An open collection of Python anti-patterns and worst practices.
https://quantifiedcode.github.io/python-anti-patterns
Other
1.72k stars 249 forks source link

Converting values to lists using list comprehensions instead of list() #114

Open AN3223 opened 6 years ago

AN3223 commented 6 years ago

Recently I've been using a lot of list comprehensions in Python. They're really useful. But I noticed that a lot of the time when I wanted to convert a generator or something into a list, I'd quickly write something like [x for x in whatever] and nothing else, when just list(whatever) would suffice. I suppose it's a readability thing?

So in short:

Anti-pattern

xs = (1, 2, 3, 4)
ys = [x for x in xs]

Best practice

xs = (1, 2, 3, 4)
ys = list(xs)
adewes commented 6 years ago

Sounds great, can you write a draft for this (have a look at a rst file to see how the anti-patterns are structured)?

AN3223 commented 6 years ago

For sure, here's a draft of it: https://gist.github.com/AN3223/344d27279be6ee87e13c5fadf1af756d

Apologies for the procrastination!

dejanbatanjac commented 5 years ago

The best for this example would be to use:

xs=(1, 2, 3, 4)
xs=[*xs]
xs # [1,2,3,4]

as [] is faster than list()

tucked commented 5 years ago

I'm not sure about that:

$ python3 -m timeit -n 1000 -s 'x = range(1000000)' -- 'list(x)'
1000 loops, best of 5: 68.1 msec per loop
$ python3 -m timeit -n 1000 -s 'x = range(1000000)' -- '[*x]'
1000 loops, best of 5: 68.3 msec per loop

FWIW, I would probably consider list() more readable anyways.

dejanbatanjac commented 5 years ago

@tucked, let it got with the list(), my tip was based on https://stackoverflow.com/questions/30216000/why-is-faster-than-list analysis.

tucked commented 5 years ago

Yes, but I suspect after a certain point, as in my example, overhead is essentially negligible compared iteration over x. Even at small scale, I would not consider the performance boost significant enough to warrant the sacrifice of readability:

$ python3 -m timeit -n 1000000 -s 'x = range(1000)' -- '[*x]'
1000000 loops, best of 5: 44.7 usec per loop
$ python3 -m timeit -n 1000000 -s 'x = range(1000)' -- 'list(x)'
1000000 loops, best of 5: 57.2 usec per loop

I would call this premature optimization, but, you know, that's just, like, my opinion, man.

dejanbatanjac commented 5 years ago

@tucked, using list() is just fine. :)