I'm pretty new at python and I was wondering if this:
def func(self, foo):
for foo in self.list:
if foo.boolfunc(): return True
return False
is good practice.
Can I return out of a loop like the above or should i use a while-loop, like so?
def func(self, foo):
found = false
while(not found & i < len(self.list)):
found = foo.boolfunc()
++i
return found
My java-professor warns us never t开发者_StackOverflowo use breaks in our loops, but this technically isn't a break and it's more concise, so... yeah
thanks
There's nothing wrong with your example, but it's better to write
def func(self, foo):
return any(foo.boolfunc() for foo in self.list)
It should be mentioned that in Python, for loops can have an else clause. The else clause is only executed when the loop terminates through exhaustion of the list.
So you could write:
def func(self):
for foo in self.list:
if foo.boolfunc():
return True
else:
return False
Your professor is advocating a practice called "Single point of Return", which basically states that any block of code should only have one point of exit. Breaks in loops are somewhat distinct from this, but usually lumped together.
It's a controversial opinion, to say the least, and certainly not as hard and fast a rule as "never use goto". It's probably worth doing it his way - you can appease him and also see the benefit of both approaches, but most people probably aren't too strict on single point of return if violating it makes their code more readable.
"Early exit" is a perfectly Pythonic style (when warranted: gnibbler's answer correctly points out that for your specific use case there's a built-in [[in Python 2.5 and better]] that's preferable) and often helps realize the Pythonic goal of "flat is better than nested". And for
is usually the right way to do looping in Python, at application-level: if there's any complicated loop logic (as might warrant a while
), it's often better to push it down to an auxiliary generator anyway.
Advantages sometimes claimed for the alternative "single point of exit" include the existence of a single "exit bottleneck" at which clean-up can be performed. But since exceptions are always possible, you don't know that your single return
is a unique exit bottleneck, even if you have it: the proper way to ensure good cleanup is, instead, the with
statement (in 2.6, or 2.5 with an "import from the future"; for older versions of Python, the clunkier but still useful try
/finally
instead).
Knuth's article "Structured Programming With Goto Statements" (pdf) -- an incredible, visionary article from 1974 by the man that many consider a living legend of computer science, both theoretical and practical -- is well worth reading. Anybody who doubts the article's applicability to Python should consider the following short quote from it:
devices like indentation, rather than delimiters, might become feasible for expressing local structure in the source language.
twenty years before Python 1.0 was published, Knuth already foresaw the key syntax aspect that was to become such a hallmark of Python (and, independently, Haskell, released a bit earlier than Python -- from personal discussion with Knuth, Peyton Jones, and van Rossum, I can attest they all claim that these three inventions of "indentation for grouping" were entirely independent from each other, just a case of "great minds think alike" -- or, in Charles Fort's words, "it was just steam engine time";-).
Formal proofs of code including early exit are of course not a jot harder than for equivalent code with single point of exit, if nothing else because the famous proof by Corrado Böhm and Giuseppe Jacopini shows how to perform a mechanical transformation from any flowchart to one containing only sequence, selection and repetition (but of course the transformed program -- just like any other program trying to avoid the early-exit style -- is prone to having more nesting than needed, and extra boolean "status" variable, which interfere with readability, directness, and efficiency -- making early-exit much superior in languages that support it well).
It is good practice.
My java-professor warns us never to use breaks in our loops
Why is that? “never” is a strong word in computer science and should never (…) be used.1)
1) Except for “goto” … we all have our pet peeves. ;-)
"Breaking out of a loop" can easily devolve to bad practice because it conceals the terminating condition of the loop.
If your if
statement is of moderate complexity, then it can become unclear what post-condition the loop establishes.
If your exit condition is obvious, then an early exit is a common syntactic optimization.
If your exit condition is not obvious, then a convoluted, nested, hard-to-follow set of if
statements is doing you more harm than good.
Indeed, this SO question shows that the presence of a simple try
block can lead to conditions so baffling that a clearly incorrect piece of code was produced and could not easily be debugged.
Generally, all "early-exit" things (the break
statement, in particular) lead to problems creating a formal proof. (The else
statement has similar problems.)
If you develop your program by reasoning out the statements required to create the necessary post-condition, you'll never need break
or an early return
because you can't easily create these statements using formal methods.
Also, note that any advice to avoid break
or else
will lead to hate mail and downvoting. For inexplicable reasons, looking closely at some programming constructs is a bad thing.
"else" considered harmful in Python?
If the exit condition of a loop with a break
(or early return
) is not obvious, you need to rework things to make it obvious.
In this example, they're obvious, so there's no issue with the specific example as presented.
精彩评论