if statements with or w/o else statements

H

Harry George

Diez B. Roggisch said:
Only if you actually have s/t senseful to do in the else. Otherwise you end
up with s/t like this:

if <cond>:
...
else:
pass

The question is, why do you need a branch? There are several reasons:

1. Exhaustive enumeration of valid paths, with an exception if none is
detected.

The "enumeration" might be just one item:
if x:
do_x
else:
raise Ex01

It might be a few:
if x:
do_x
elif y:
do_y
else:
raise Ex02

It might be a whole lot of choices, in which case some table lookup
should be used with the exception raised if no lookup case is
found.


2. Partial Enumeration. For this, we do not know that an exception
has occurred if we fall off the list. So we leave off the "else".
Or for clarity, to make very clear that it is optional, we can use

else:
pass

However, I only do that if there confusion on whether or not it
really ought to be full enumeration.
 
B

Bart Nessux

Should an if statement have a corresponding else statement? Or, is it OK
to have an if statement by itself. For completeness, it seems the two
should be together, but from experience I know that a if statement by
itself works just fine. Below is an example:

if x >=0:
DO SOMETHING

Would it be better, or perhaps more complete, written like this:

if x >=0:
DO SOMETHING
else:
DO SOMETHING ELSE
 
D

Diez B. Roggisch

Bart said:
Should an if statement have a corresponding else statement? Or, is it OK
to have an if statement by itself. For completeness, it seems the two
should be together, but from experience I know that a if statement by
itself works just fine. Below is an example:

Only if you actually have s/t senseful to do in the else. Otherwise you end
up with s/t like this:

if <cond>:
...
else:
pass
 
M

Mark McEahern

Should an if statement have a corresponding else statement?

Syntactically, the answer is no--the else statement is optional.

Logically, though, consider this:

if preCondition:
doSomething()

That is, e.g., you're testing for a pre-condition that, if false,
indicates failure. In that case, NOT having an else statement is likely
to mask subtle bugs and it's probably better to have:

if preCondition:
doSomething()
else:
raise RuntimeError('X must be true.')

which itself can be expressed differently so that you don't need the
else, e.g.,

if not preCondition:
raise RuntimeError(...)
doSomething()

;-)

Cheers,

// m
 
P

Peter Otten

Bart said:
Should an if statement have a corresponding else statement? Or, is it OK
to have an if statement by itself. For completeness, it seems the two
should be together, but from experience I know that a if statement by
itself works just fine. Below is an example:

if x >=0:
DO SOMETHING

Would it be better, or perhaps more complete, written like this:

if x >=0:
DO SOMETHING
else:
DO SOMETHING ELSE

No direct answer, but a good way to learn about this kind of questions is to
study real code, and the best way to learn from the masters would probably
be to look into the python library.

Now, from the pointless statistics department, a little script that counts
occurences of both if and if...else:

<ifstats.py>
#!/usr/bin/env python
""" Analyse if statements in python scripts
"""
__author__ = "Peter Otten"
__category__ = "Pointless statistics"

import compiler

class IfStats:
def __init__(self):
self.total = 0
self.withElse = 0
def __str__(self):
return "%d of %d if statements have an else branch" %
(self.withElse, self.total)
def visitIf(self, node):
self.total += 1
if node.else_:
self.withElse += 1

if __name__ == "__main__":
import os, sys, optparse
parser = optparse.OptionParser(
usage="usage: \%ifstats [-v] [-r] folder1 ... folderN",
description="scan python scripts for if statements with or without
else branch")
parser.add_option("-v", "--verbose", action="store_true",
help="print info about every processed file")
parser.add_option("-r", "--recursive", action="store_true",
help="recursively collect files")
options, args = parser.parse_args()

totalFiles = 0
totalIf = 0
totalWithElse = 0
failed = 0
for root in args:
for path, folders, files in os.walk(root):
for fn in files:
if fn.endswith(".py"):
fp = os.path.join(path, fn)
try:
a = compiler.parseFile(fp)
except:
failed += 1
print >> sys.stderr, "%s --> FAILED" % fp
else:
stats = IfStats()
compiler.walk(a, stats)
if options.verbose:
print "%s --> %s" % (fp, stats)
else:
sys.stdout.write(".")
sys.stdout.flush()
totalIf += stats.total
totalWithElse += stats.withElse
totalFiles += 1
if not options.recursive: break
print
print "%d of %d if statements with else branch" % (totalWithElse,
totalIf)
print "in %d files" % totalFiles
if failed:
print "parsing failed for %d files" % failed
</ifstats.py>

It turns out that only 2039 of 11157 if statements in the standard library
have an else branch. Now draw your own conclusions...

Peter
 
D

Dang Griffith

That is, e.g., you're testing for a pre-condition that, if false,
indicates failure. In that case, NOT having an else statement is likely
to mask subtle bugs and it's probably better to have:

if preCondition:
doSomething()
else:
raise RuntimeError('X must be true.')

which itself can be expressed differently so that you don't need the
else, e.g.,

if not preCondition:
raise RuntimeError(...)
doSomething()
In general, I recommend avoiding "negative" test conditions like this.
However, I recommend them for testing preconditions at the start (or
as early as possible) of a method. When there are multiple,
related/dependent preconditions, using positive tests can lead to
having the *useful* code nested in a confusing bunch of conditions.

Using a linear sequence of negative test conditions at the top makes
it more clear that it is indeed the preconditions being tested
(because the code exits/returns/raises when the condition is true),
rather than business logic. Plus, the business logic is not
unnecessarily indented, which also help avoid long lines wrapping
(your editor and printer prefences may vary).
--dang
 
B

Bart Nessux

Peter said:
Bart Nessux wrote:

Should an if statement have a corresponding else statement? Or, is it OK
to have an if statement by itself. For completeness, it seems the two
should be together, but from experience I know that a if statement by
itself works just fine. Below is an example:

if x >=0:
DO SOMETHING

Would it be better, or perhaps more complete, written like this:

if x >=0:
DO SOMETHING
else:
DO SOMETHING ELSE


No direct answer, but a good way to learn about this kind of questions is to
study real code, and the best way to learn from the masters would probably
be to look into the python library.

Now, from the pointless statistics department, a little script that counts
occurences of both if and if...else:

<ifstats.py>
#!/usr/bin/env python
""" Analyse if statements in python scripts
"""
__author__ = "Peter Otten"
__category__ = "Pointless statistics"

import compiler

class IfStats:
def __init__(self):
self.total = 0
self.withElse = 0
def __str__(self):
return "%d of %d if statements have an else branch" %
(self.withElse, self.total)
def visitIf(self, node):
self.total += 1
if node.else_:
self.withElse += 1

if __name__ == "__main__":
import os, sys, optparse
parser = optparse.OptionParser(
usage="usage: \%ifstats [-v] [-r] folder1 ... folderN",
description="scan python scripts for if statements with or without
else branch")
parser.add_option("-v", "--verbose", action="store_true",
help="print info about every processed file")
parser.add_option("-r", "--recursive", action="store_true",
help="recursively collect files")
options, args = parser.parse_args()

totalFiles = 0
totalIf = 0
totalWithElse = 0
failed = 0
for root in args:
for path, folders, files in os.walk(root):
for fn in files:
if fn.endswith(".py"):
fp = os.path.join(path, fn)
try:
a = compiler.parseFile(fp)
except:
failed += 1
print >> sys.stderr, "%s --> FAILED" % fp
else:
stats = IfStats()
compiler.walk(a, stats)
if options.verbose:
print "%s --> %s" % (fp, stats)
else:
sys.stdout.write(".")
sys.stdout.flush()
totalIf += stats.total
totalWithElse += stats.withElse
totalFiles += 1
if not options.recursive: break
print
print "%d of %d if statements with else branch" % (totalWithElse,
totalIf)
print "in %d files" % totalFiles
if failed:
print "parsing failed for %d files" % failed
</ifstats.py>

It turns out that only 2039 of 11157 if statements in the standard library
have an else branch. Now draw your own conclusions...

Peter

Thanks Peter. That's an easy conclusion to come to.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top