Какой питонический способ обозначить недостижимый код в python, как в:
gender = readFromDB(...) # either 'm' or 'f'
if gender == 'm':
greeting = 'Mr.'
elif gender == 'f':
greeting = 'Ms.'
else:
# What should this line say?
Какой питонический способ обозначить недостижимый код в python, как в:
gender = readFromDB(...) # either 'm' or 'f'
if gender == 'm':
greeting = 'Mr.'
elif gender == 'f':
greeting = 'Ms.'
else:
# What should this line say?
raise ValueError('invalid gender %r' % gender)
Это зависит от того, насколько вы уверены в том, что пол имеет значение 'm'
или 'f'
.
Если вы абсолютно уверены, используйте if...else
вместо if...elif...else
. Просто облегчает для всех.
Если у вас есть шанс на неверные данные, вы, вероятно, должны создать исключение, чтобы упростить тестирование и исправление ошибок. В этом случае вы можете использовать нейтральное по гендерному признаку приветствие, но для чего-то большего, специальные значения просто затрудняют поиск ошибок.
Вы можете создать исключение:
raise ValueError("Unexpected gender; expected 'm' or 'f', got %s" % gender)
или используйте assert False, если вы ожидаете, что база данных вернет только "m" или "f":
assert False, "Unexpected gender; expected 'm' or 'f', got %s" % gender
Я действительно думаю, что есть место для этого.
class SeriousDesignError( Exception ):
pass
Итак, вы можете сделать это
if number % 2 == 0:
result = "Even"
elif number % 2 == 1:
result = "Odd"
else:
raise SeriousDesignError()
Я думаю, что это наиболее значимое сообщение об ошибке. Такие вещи могут возникать только из-за ошибок дизайна (или плохого обслуживания, что является одним и тем же.)
Это зависит от того, что вы хотите сообщить об ошибке, но я бы использовал словарь в этом случае:
greetings={'m':'Mr.', 'f':'Ms.'}
gender = readFromDB(...) # either 'm' or 'f'
greeting=greetings[gender]
Если пол не является ни m, ни f, это приведет к увеличению KeyError, содержащему неожиданное значение:
greetings={'m':'Mr.', 'f':'Ms.'}
>>> greetings['W']
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
greetings['W']
KeyError: 'W'
Если вы хотите получить больше подробностей в сообщении, вы можете поймать и сделать ререйз:
try:
greeting = greetings[gender]
except KeyError,e:
raise ValueError('Unrecognized gender %s'%gender)
До сих пор я обычно использовал вариацию ответа Джона Фухи - но это не совсем правильно, как указывает Итан:
assert gender in ('m', 'f')
if gender == 'm':
greeting = 'Mr.'
else:
greeting = 'Ms.'
Основная проблема с использованием assert заключается в том, что если кто-то запускает ваш код с помощью флагов -O или -OO, утверждения будут оптимизированы. Как указывает Итан ниже, это означает, что теперь у вас нет проверок данных вообще. Утверждения являются вспомогательным средством развития и не должны использоваться для производственной логики. Вместо этого я привык использовать функцию check() - это позволяет использовать чистый синтаксис вызова, например assert:
def check(condition, msg=None):
if not condition:
raise ValueError(msg or '')
check(gender in ('m', 'f'))
if gender == 'm':
greeting = 'Mr.'
else:
greeting = 'Ms.'
Возвращаясь к исходному вопросу, я бы сказал, что использование функции assert() или check() перед логикой if/else легче читать, безопаснее и более явным:
Я иногда делаю:
if gender == 'm':
greeting = 'Mr.'
else:
assert gender == 'f'
greeting = 'Ms.'
Я думаю, что это хорошо говорит читателю кода, что есть только (в данном случае) две возможности и то, что они есть. Хотя вы можете сделать пример для создания более описательной ошибки, чем AssertionError.