Hacker Newsnew | past | comments | ask | show | jobs | submit | vadim41's commentslogin

Cute oneliners that are close to unreadable and definitely unmaintainable.

If I see this kind of "cute" code in code reviews, there is some serious scolding to be done.


Eh, while comprehensions with multiple for-ins push the limits of good taste, I don't think:

    planets_set = {
        planet for episode in episodes.values() 
        for planet in episode['planets']
    }
is less maintainable in a Python shop than say...

    planets = set()

    for episode in episodes.values():
        planets.update(episode['planets'])
Although the latter will likely make perfect sense to most non-python developers. The former is faster and has a smaller memory footprint and might be preferred when dealing with a larger or more irregular data sets.

The former also has the advantage of not leaking the "episode" variable into the function/method scope, which could introduce a subtle bug if that variable gets conditionally reused. So while it's harder to understand for a less-experienced python developer, the set comprehension solution is inherently safer due to python's design.


Additionally, generator comprehensions can be far more efficient than any simple for loop. If you had a generator with a billion star coordinates being read from some file, you'd never be able to load it all into memory. So, instead of manually making a generator function, you could just do

    coordinates = (star.x, star.y, star.z for star in star_map)


Though in py2 list comprehensions do leak scope. (dict comprehensions don't, you are correct on that :).


Gosh. If I was told off for using list comprehensions I'd start considering my employment options fairly quickly. Whilst they can be abused and pushed beyond the limits of reasonable use - in most cases I've seen in the wild they are the clearest and most Pythonic way to do it.


That seems a little harsh.

Nested list comprehensions with multiple filtering if statements? Scald away.

But the simpler examples there are perfectly readable, understandable and maintainable if you understand list comprehensions. And if you need to alter it to the point where it needs to be a little more verbose in order to convey what you're doing, then sure, you can break it out into some other structure. But just because the complexity might increase later on doesn't mean that you shouldn't use a list comprehension.


But what do you gain from using nested list comprehension like that? There's no performance gain (or very, very little). The only tangible benefit I see is saving a few lines of code.

And for those few lines of code you've traded the ability for new programmers to understand it easily. To me that's a net loss.


New programmers should learn how to use list comprehensions. They're not just some obscure Python concept, they appear in multiple other languages, as well as mathematics.


It's actually much more sensible code a lot of the time, especially for people who didn't get a degree that consisted of a lot of for-looping in class.

    good_jedis = [jedi for jedi in universe if jedi.alignment == "good"]
vs.

    good_jedis = []
    for jedi in universe:
        if jedi.alignment == "good":
            good_jedis.append(jedi)
And then when you get on stuff like dictionary comprehensions and generator expressions, it starts becoming an amazing tool that is able to accomplish things that are straight-up cumbersome with old loops.

There's a computer science course out there that a friend was telling me about, that begins by showing students how to "map" a function over an iterable, way way before a "for loop" ever shows up. I think this is the way it should be done, "for loops" as a three-line-structure only seem natural to people who grew up programming for loops.


for-ins leak iteration variables into the function scope, which can introduce subtle bugs if you're not careful.

set/dict/generator comprehensions do not.

Example:

   for foo in bar:
     baz(foo)
   
   print foo  # Will actually print something

Whereas

   whatever = {baz(foo) for foo in bar}
   print foo # NameError: name 'foo' is not defined
does not put foo into the outer scope.

list comprehensions in python 2 (but not 3) will leak variables however.


There is always a performance gain, and sometimes it can be fairly huge.


Actually, these are pretty idiomatic and understandable.

List comprehensions (and inline generators, which you get by using parenthesis) make it trivial to handle fairly complex sequence processing, and are one of the reasons Python gets a lot of love from the FP community.

Sure, it's not really an FP language, but these give it an almost LISPy feel.

Regardless,it would be less Pythonic to build a loop and iterate.

Might be easier for complete novices, but I don't suppose people are just hiring novices these days, right?

(edit: Mobile-sponsored typo)


List comprehensions are both insanely readable and easy to maintain. They're one of the things python gets very, very right


I just learned about this, so they are unreadable to me.

But it's not relevant. What relevant is, do they create a readability problem for a python developer who spent significant time with them? I honestly don't know.


I 'got' list comprehensions fairly immediately and find them clearer in most cases than map/filter for an explicit loop. I'm cautious when nesting them (as long as your code formatting is clear - a single nested comprehension is pretty acceptable) and I never use the multiple 'for' form as it's just not intuitive to me.

I am rather fond of dictionary comprehensions as mentioned in the article:

    colors = [jedi['lightsaber_color'] for jedi in jedis]
    frequencies = {color: colors.count(color) for color in set(colors)}

    print(frequencies)
    # {'green': 6, 'red': 5, 'blue': 6}


I think the biggest reason python map/filter aren't natural is the building outwards (though I do realize it's lispy and some people might prefer it).

Languages that support it directly on a list are much more intuitive in my head: list.filter().map()...

Alternatively, pull in syntax like elixir (and other languages) have to make chaining a breeze:

list |> map() |> filter()


Really? I am pretty much mind-blown when the first time I learned about this. Given that my background is Mathematics, I thought it was pretty elegant and also looked very intuitive.


I think I'd resign if someone in a position to be reviewing Python code scolded me for using a list/dict/set/generator comprehension.


That's not really "cute" code though. Short list comprehension isn't any less readable (and certainly not less maintainable WTF?) than a multi-line "for" loop. In fact, I find short list comprehension more readable. I don't have to mentally keep track of place in a multistep loop.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: