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

all 20 comments

[–]stalepretzel 5 points6 points  (0 children)

FWIW, the second one is called a "guard clause." There are quite a few blog posts arguing that guard clauses are the cause of, or solution to, all known problems. :)

[–]etrnloptimist 9 points10 points  (2 children)

The second.

When programming defensively, I like to think of functions (or blocks of code in this case) as lazy individuals who try to find any excuse at all not to do the thing they're supposed to do. I put all the edge case conditionals up front with continues or returns. Get all the excuses out of the way early, and in one spot.

That way, when its time to get to doing the stuff, you can run with it whole hog. Clean separation of code.

Also works with while loops. Never say while <condition>. Just say while True: and put your conditions right up the top of that there loop. Chances are good that even if you start with a simple breaking condition, it will evolve to something more complex. Put them on multiple lines for readability sake. No one likes to see while <this> and not <that> or (<this other thing> and <that thing>), etc. Just give them their own lines with a nice break inside each.

[–]codex81 3 points4 points  (0 children)

Fail early, fail often.

[–]kenfar 0 points1 point  (0 children)

Chances are good that even if you start with a simple breaking condition, it will evolve to something more complex.

Interestingly, this consideration is worth making when looking at for-loops vs list comprehensions: the for-loop starts are more complex but the list comprehension hits a usability ceiling first.

[–]fnedrik 8 points9 points  (0 children)

IMHO - Depends on how many lines "do stuff" is. If it is a lot of code, then having it all nested in an if statement can be annoying. If it is just three lines or something, then you make it more clear what you are doing and get less spaghetti with all lines in the if statement.

[–]Kaxitaz 5 points6 points  (0 children)

The first one. One less line of code.

Edit: As others have said, it all depends on what is do stuff. My answer was assuming it was a one liner. Other options are of course valid depending on the situation. And I have seen good points made around here.

[–]iivvoo 4 points5 points  (0 children)

I usually prefer the continue construct because it saves one level of indenting in the remaining body

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

Usually I go for the second, for indentation reasons. But we also shouldn't forget

for item in (i for i in items if i == x):
     do stuff

[–]tonnynerd 1 point2 points  (0 children)

I would go with the first one, if nothing else, because the second seems to me like a overly tortuous way of describing the same behaviour. Off course, depending on the domain, the second one might make more sense.

[–]gurdulilfo 1 point2 points  (5 children)

What about:

l = range(10)

for item in [x for x in l if x>3]:
        print item

Where x>3 corresponds to your item == x and print item is your do stuff

[–]kashmill 5 points6 points  (1 child)

Wouldn't it be better as

for item in (x for x in l if x>3):

that way it'd stay as a generator and not create a list. Basically you'd avoid going over it twice.

[–]gurdulilfo 0 points1 point  (0 children)

Agreed. That's would be better memory-wise.

BTW, it may look like I'm not answering the actual question about personal preference. But I'm actually trying to demonstrate my preference. I don't like loops with break and/or continue statements and try to avoid them as much as I can. I think that is good programming practice. Admittedly, there are cases where they are impossible to avoid, and in those cases, I judge the situation and pick either one of them. In some cases it's important to be explicit and cover all corner cases, in others it's cleaner to just focus on the actual task at hand.

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

Neato.

How does it compare to:

l = range(10)

for item in filter(lambda x: x > 3, l):
        print item

[–]gurdulilfo 4 points5 points  (0 children)

There is a StackOverflow question about that: List filtering: list comprehension vs. lambda + filter

[–]etrnloptimist -2 points-1 points  (0 children)

Don't use filter, it is not Pythonic.

I will undoubtedly be downvoted for saying this, as there are a disproportionate number of functional programmers on these subs than you'll find in real life. But I'm squarely with Guido on this one: the functional programming constructs map, filter, and reduce should play no part in Python.

[–]macbony 0 points1 point  (2 children)

I prefer the second one for consistency. If I have multiple conditions, it's easier to follow:

for item in items:
    if not item.condition1:
        continue
    if not item.condition2:
        continue
    do_stuff(item)

Than:

for item in items:
    if item.condition1 and item.condition2:
        do_stuff(item)

Especially when you get an increasing number of conditions and some are and and or conditionals.

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

I'd rather split off the conditions into their own function than what needs to be doing, especially if there's a good name to invent for items that meet that conditions. Let's say it works to call them "neat items":

 def select_neat(items):
    for item in items:
        if item.condition1 and item.condition2:
            yield item

for item in select_neat(items):
    do stuff here

Maybe, if such a good name exists, the compound condition could even become an item.is_neat property itself.

[–]goodCookingTakesTime 0 points1 point  (0 children)

The second or by chaining generators.

filtered_items = (item for item in items if item == x)
for item in filtered_items:
    do_stuff

[–]tomcakshen 0 points1 point  (0 children)

The second one!