3 ms·
I love Python but my personal hate goes for this when used in list comprehensions. a = [1,2,3] # list comprehension with if [ x for x in a if x > 1
by Uberphallus 5y ago
I love Python but my personal hate goes for this when used in list comprehensions.
a = [1,2,3]
# list comprehension with if
[ x for x in a if x > 1]
[2, 3]
# list comprehension with if/else
[ x if x > 1 else x*2 for x in a]
[2, 2, 3]
When it's just "if" it goes after the "for", when it's "if/else" it goes, all of it, before. I still don't understand why it's this way, it doesn't even make sense even reading it in natural language. I much prefer the mathematical-like syntax present in Scala for this.
Edit: Thanks for the responses, they are are insightful, never thought of this that way.
Still in my head the lack of "else" clause implies filtering no matter where, while its presence implies transformation no matter where. The first element of the list is always transformed (though in this example it's identity).
I think it's a case of Python trying to do too much with too little. Personally for anything relatively complicated I still prefer to use filter() and map() as list comprehensions can get unwieldly quick.
- inanutshellus 5y agoThe "before" is what value is returned, the "after" is whether it should be returned. In your case you were conditionally choosing a manipulated return value for x and didn't care at all about filtering the list. Here's one with both: [x if x > y else x*2 for x in a if x % 2 == 0] ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ return x as... filter down to only... x or x*2 even 'x's There's not really a semantically logical place for an "else" in the latter half because it's only looking for a true statement so it can return x (or not). For example this makes sense: ... if x % 2 == 0 or x == 3 (filter the list to even values of x or the value 3) but this does not: ... if x % 2 == 0 else x == 3 (filter the list to even values, otherwise wait, otherwise?)
- pierrebai 5y agoThe point is not that we're idiots who don't know the language, but that functional-style ordering does not align with human cognitive cues. The problem is that functional-style fails to separate essential bits and fails to give strong visual clues where each bits begins and ends. That is why the old imperative style is clearer. Compare: for i in container: do something with i and [do something with i for i in container] One has a clear separation of loop and action, the other requires scanning for the "for i" in the middle. This generalize to other similar construct, and the Python ternary operator has the same flaw. The imperative if / else version clearly separate alternatives on separate lines. IMO, syntax design should always try to learn from the imperative style and always strive to produce a syntax that clearly separate each logical item in a compound statement, and using different lines is one of the best for us human to visually grok. (That's why even Lisper will often format their code to separate bits on different lines!)
- inanutshellus 5y agoDon't be a jerk. OP clearly stated he didn't understand it: > When it's just "if" it goes after the "for", when it's "if/else" it goes, all of it, before. I still don't understand why it's this way and discussing it here on HN shouldn't be punished. ... Back to the topic at hand ... List comprehensions save you enough syntax to be worth it, IMHO: mylist=[] for i in container: if i > 10: mylist.append(i*2) vs mylist = [x*2 for x in container if x > 10] ... That's a very terse, clean request for work and arguably it's easier to read than "for(int i=0; i<10; i++)", which we've all acclimated to by the end of CS101. I think they're quite worth the trade-off.
- jodrellblank 5y agoThe first is a transform of the values (with only that, the list stays the same length, the IF says whether the transform happens or doesn't for each value), the second is a WHERE filter picking or dropping some values (list might shrink), you can have both (list shrinks and the selected values are transformed): >>> list([ x if x > 1 else x*2 for x in a if x <3] ) [2, 4]
- omegalulw 5y ago> but my personal hate goes for this when used in list comprehensions. I feel you. I still use them though because they are still more readable then alternatives.