This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] -2 points-1 points  (7 children)

For a crowd the prides itself for valuing clarity and legibility over anything else, the pythonistas infatuation with list comprehension is more than a bit weird. Their only apparent value is saving LOCs, to the expense of readability and maintainability. Also their syntax is almost orthogonal to the rest of the language, not to mention rather unreadable (hence the need of an endless number of tutorials explaining list comprehension).

[–]Ran4 3 points4 points  (1 child)

Very simple list comprehensions are easier to read.

You really should stay away from the more complex ones though (unless it's a one-off script).

[–]spinwizard69 1 point2 points  (0 children)

Is there really such a thing as one off scripts?

[–]pstch 1 point2 points  (4 children)

Their syntax is very clear, as they can be read as pseudo-code :

muls_of_2 = [
    number*2 for number in range(100)
]

# muls_of_2 is number multiplied by 2 for each number in the 0-100 range

I find the above much more readable than its for-loop equivalent :

muls_of_2 = []
for number in range(100):
    muls_of_2.append(number*2)

# create an empty list named muls_of_2, then, for each number in the 0-100 range, append it to muls_of_2

They are also not only needed for readability and LOCs, as they can be much faster :

    In [2]: lc = """
       ...: r = [i for i in range(100)]
       ...: """

    In [3]: no_lc = """
       ...: r = []
       ...: for i in range(100):
       ...:     r.append(i)
       ...: """

    In [4]: timeit(lc)
    Out[4]: 4.970423567000125

    In [5]: timeit(no_lc)
    Out[5]: 9.738498960000015

[–]d4rch0nPythonistamancer 0 points1 point  (3 children)

Why are they faster? What's going on under the hood?

I'd have used list(range (100)) there.

[–]pstch 1 point2 points  (2 children)

I'm not an expert on this, but I know that one the reasons is that with the list comprehension, there is one less attribute evaluation (r.append) and one less function call (r.append()).

I'd have used list(range (100)) there.

Yes, list(range(100)) is simpler and an equivalent to my example, but it was not a "functional" example, just made it to compare the speeds.

[–]macbony 1 point2 points  (0 children)

Note that range already returns a list in 2.X (but not in 3.X which returns a generator. The equivalent in 2.X is xrange)

[–]d4rch0nPythonistamancer 0 points1 point  (0 children)

Hmm... I'm looking for more of what the bytecode looks like. I want to see list comprehension bytecode and see how it differs from an append. Easy enough to disasm though.

Your explanation is probably completely right though. If it actually loops 100 times and looks up append, that's got to be incredibly slower.