0

Hope it's not been asked before, which one of these is considered better / faster / more 'pythonic'? break after check:

while True:
    #returns either a `page` or None
    p += 1
    page = self.page_has_articles(p) 
    if page:
        yield page
    else:
        break

or first check and break:

while True:
    p += 1
    page = self.page_has_articles(p)
    if not page:
        break
    yield page
ToonAlfrink
  • 2,501
  • 2
  • 19
  • 19
  • "Better" is subjective and is therefore a bit off-topic for SO. Are you able to modify your post to ask a question that can be objectively answered? If not, you may want to consider asking this on http://codereview.stackexchange.com . – George Cummins May 23 '13 at 18:09
  • What do *you* think is more readable? – Martijn Pieters May 23 '13 at 18:11
  • FWIW, this is one reason why I always with python had a `until` clause of some sort ... but it is what it is. – mgilson May 23 '13 at 18:23
  • 1
    @mgilson: that's the one disadvantage of using indentation as a block delimiter; you cannot have constructs that require a loop controlling statement at the *end* of the block. Hence, we use `while` and live with it. :-) – Martijn Pieters May 23 '13 at 18:28
  • In the case of this small example it doesn't really matter, in the case of having more code before yielding, I would definitely take the *first check and break* approach because it gets rid of an indentation level and clearly shows the break at the top. – Wessie May 23 '13 at 18:30
  • @MartijnPieters -- Yeah. I've never been able to tackle the semantics of something like that either...(though I have thought about it). Using indentation as a block delimiter is one of my biggest complaints about python for the same reasons that Bryan Oakley brings up in this answer and comments: http://stackoverflow.com/a/1995278/748858 – mgilson May 23 '13 at 18:30

2 Answers2

1

In the (small) example given there is no clear difference between the two on first glance. However if we take an approach of error early or return early. It is clearly better to do the break and any cleaning up first.

This gets even clearer when the code used increases in line count. When reading code it is easier to take a mental note of if there is no page, we break than if there is a page, we do this, and if it isn't, we break.

So for sake of readability on (larger) blocks of code the approach of using break early has an advantage (in my opinion).

Wessie
  • 3,460
  • 2
  • 13
  • 17
0

You could use itertools to do you dirty work instead of rolling your own loop.

import itertools as it

def enumerate_pages(self,start_p):
    return it.takewhile(bool,it.imap(self.page_has_articles,it.count(start_p,1)))

takewhile, imap, and count all return iterable objects, so will work just as your while loops given as example in your question.

it.count(start_p,1) iterates from start_p with a step of 1.

it.imap() performs just like map() in python 2.x, but returns an iterable instead of a list.

it.takewhile() stops iteration at the first element to return False from the given predicate function, which in this case is bool()

mtadd
  • 2,495
  • 15
  • 18