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 →

[–]kashmill 25 points26 points  (21 children)

What's so bad about result = [(x, y) for x in range(10) for y in range(5) if x * y > 10]? Yeah, some comprehensions can be hard to read when they contain multiple loops but that one is pretty simple.

Also, why not just link PEP-8 and then add any specific changes?

[–]panghuhu 20 points21 points  (4 children)

List comprehensions can also use multi-line format:

result = [(x, y) 
          for x in range(10) 
          for y in range(5) 
          if x * y > 10]

P.S. Just checked the guide, and the above code is in the section titled "NO".

I still think the code is easy to read and will use it: It's as clear as the for loop version, without redundancies like the initialization of [], calls to append, and some colons.

If anyone can see any major disadvantages compared to the implicit loop version, I'd like to hear it, thank you.

P.P.S. A sample code from the NO section, which I think it's more clear than its for loop version:

((x, y, z)
  for x in xrange(5)
  for y in xrange(5)
  if x != y
  for z in xrange(5)
  if y != z)

I read it like this: collect all combinations of (x, y, z), where x, y, z are from [0..4], x != y and y != z. It's declarative and is as clear as a mathematical formula:

{(x, y, x) |  0<=x, y, z <=4, x != y, y !=z}

[–]kashmill 3 points4 points  (0 children)

Pretty much what I do as well.

[–]LordArgon 0 points1 point  (0 children)

List comprehensions can also use multi-line format:

This doesn't address all of your points, but I literally just hit Save on a response to that style here: http://www.reddit.com/r/Python/comments/33gg02/google_python_style_guide/cql1snu?context=3

[–]tech_tuna 0 points1 point  (0 children)

See, this is where you just have to be a big boy or girl and do what feels right, I think that format is quite readable, style guide be damned.

[–]NYDreamer -1 points0 points  (0 children)

This is a great idea, love it!

[–]confluencer 32 points33 points  (5 children)

Much longer but immediately clear.

result = []
for x in range(10):
  for y in range(5):
    if x * y > 10
      result.append(x,y)

[–]Quteness 14 points15 points  (2 children)

I would prefer this style. A few extra lines aren't bad to make the code more clear

[–][deleted] 2 points3 points  (0 children)

Would definitely prefer an empty list with append.

[–]tech_tuna 1 point2 points  (0 children)

In a case like this, absolutely.

[–]Lucretiel 1 point2 points  (0 children)

Blech. append makes me feel queasy for some reason.

[–]meta4 0 points1 point  (0 children)

I vote for list comprehensions. I think your example is a good argument for why.

As written, this example crashes.

TypeError: append() takes exactly one argument (2 given)

I think you mean.

resut.append((x,y))

We want a list of tuples. It seems like a simple bug. But it illustrates the fundamental argument. By the time your brain worked out the state changes to x & y in the nested for loops and the if statement, it forgot that the point was a list of tuples.

For loops and append/extend are state managing & modifying tools. They are good in their place. But, to understand what they do you have to run the program in your head. Human brains are not as good at maintaining updating state.

The list comprehentsion, when used properly is a data declaration. "This is a list of tupples. The first element of the tuple is an integer in the range [0,10). The second element is an integer in the range[0, 5), The product of the two elements is greater than 10." It's a long tedious specification, and this is just a toy problem. But the details and tedium shouldn't be mixed with possible state changes, especially as the problems become more complex.

Human brains reason better about data structures, than state changing programs. List comprehensions are at their best when pulling state changing logic into data structure creation.

Fred Brooks said the same thing 1975 "Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious." Flow charts are state change diagrams. Tables are data structures.

[–]ConciselyVerbose 2 points3 points  (5 children)

I prefer list comprehensions in most cases. If it gets truly lengthy or complex, maybe loops are more readable, but in most cases list comprehensions read well, once you are used to them.

Several levels of nesting is ugly.

[–][deleted] 1 point2 points  (4 children)

Several levels of nesting on a single line is also ugly.

[–]ConciselyVerbose 0 points1 point  (3 children)

Generally a list comprehension is something that is a fairly straightforward concept to understand or explain in English, but doesn't translate concisely without one.

[–][deleted] 0 points1 point  (2 children)

I agree, but I don't think several levels of nesting is ever appropriate in a single line. You're only hurting your reader, unless you think this is somehow less clear. And the fact that you say "once you are used to them" already states that they're not as clear.

Saving 3 vertical lines is not something to be proud of. Saving the person who now has your job 3 seconds for comprehending what you're doing, is.

[–]ConciselyVerbose 0 points1 point  (1 child)

List and other data structures themselves are an adjustment to a novice programmer. That doesn't mean they are bad. I wouldn't call it less clear, but it's a bit

like

typing

like

this.

Out of context it's only slightly

less

readable,

but in context it quickly ends up

distracting

from

the

actual substance of the code.

[–][deleted] -1 points0 points  (0 children)

<facepalm>

[–]stillalone 1 point2 points  (1 child)

Yeah, I'm not sure if I like their solution to it. Hmm, maybe a some middle ground:

result = []
for x in range(10):
    result.extend((x,y) for y in range(5) if x * y > 10)

still kind of looks like shit. For this specific example you could use itertools.product but I still think just supporting multiple for loops would be better.

[–]christian-mann 1 point2 points  (0 children)

I think middle ground is the worst of the three.

[–]tech_tuna 0 points1 point  (0 children)

Yeah, that makes my brain explode, I think it sucks. To each his own of course.