views:

213

answers:

6

What's the pythonic way to designate unreachable code in python as in:

gender = readFromDB(...) # either 'm' or 'f'
if gender == 'm':
    greeting = 'Mr.'
elif gender == 'f':
    greeting = 'Ms.'
else:
    # What should this line say?
+16  A: 
raise ValueError('invalid gender %r' % gender)
Dave
From the pythonic manifesto..."...Errors should never pass silently.Unless explicitly silenced."
jottos
+6  A: 

This depends on how sure you are of the gender being either 'm' or 'f'.

If you're absolutely certain, use if...else instead of if...elif...else. Just makes it easier for everyone.

If there's any chance of malformed data, however, you should probably raise an exception to make testing and bug-fixing easier. You could use a gender-neutral greeting in this case, but for anything bigger, special values just make bugs harder to find.

zenazn
/Which/ exception type would you suggest? And everyone seems to get caught up in the example ;).
phihag
Probably `ValueError` as suggested by others. It seems to make the most sense: http://docs.python.org/library/exceptions.html
zenazn
+4  A: 

You could raise an exception:

raise ValueError("Unexpected gender; expected 'm' or 'f', got %s" % gender)

or use an assert False if you expect the database to return only 'm' or 'f':

assert False, "Unexpected gender; expected 'm' or 'f', got %s" % gender
marcog
I think you mean 'assert False' :)
Stephan202
meh, fixed thanks :)
marcog
+1  A: 

I actually think that there's a place for this.

class SeriousDesignError( Exception ):
    pass

So you can do this

if number % 2 == 0:
    result = "Even"
elif number % 2 == 1:
    result = "Odd"
else:
    raise SeriousDesignError()

I think this is the most meaningful error message. This kind of thing can only arise through design errors (or bad maintenance, which is the same thing.)

S.Lott
+2  A: 

I sometimes do:

if gender == 'm':
    greeting = 'Mr.'
else:
    assert gender == 'f'
    greeting = 'Ms.'

I think this does a good job of telling a reader of the code that there are only (in this case) two possibilities, and what they are. Although you could make a case for raising a more descriptive error than AssertionError.

John Fouhy
+3  A: 

It depends exactly what you want the error to signal, but I would use a dictionary in this case:

greetings={'m':'Mr.', 'f':'Ms.'}
gender = readFromDB(...) # either 'm' or 'f'
greeting=greetings[gender]

If gender is neither m nor f, this will raise a KeyError containing the unexpected value:

greetings={'m':'Mr.', 'f':'Ms.'}

>>> greetings['W']

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    greetings['W']
KeyError: 'W'

If you want more detail in the message, you can catch & reraise it:

try:
  greeting = greetings[gender]
except KeyError,e:
  raise ValueError('Unrecognized gender %s'%gender)
Vicki Laidler