Как обозначить недоступный код Python - PullRequest
12 голосов
/ 02 мая 2009

Что означает Python для обозначения недоступного кода в Python, например:

gender = readFromDB(...) # either 'm' or 'f'
if gender == 'm':
    greeting = 'Mr.'
elif gender == 'f':
    greeting = 'Ms.'
else:
    # What should this line say?

Ответы [ 7 ]

25 голосов
/ 02 мая 2009
raise ValueError('invalid gender %r' % gender)
7 голосов
/ 02 мая 2009

Вы можете вызвать исключение:

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
7 голосов
/ 02 мая 2009

Это зависит от того, насколько вы уверены, что вы пол: 'm' или 'f'.

Если вы абсолютно уверены, используйте if...else вместо if...elif...else. Просто всем легче.

Однако, если есть вероятность искаженных данных, вам следует выдвинуть исключение, чтобы упростить тестирование и исправление ошибок. В этом случае вы можете использовать нейтральное по полу приветствие, но для чего-то большего, специальные значения просто затрудняют поиск ошибок.

5 голосов
/ 03 мая 2009

Я действительно думаю, что есть место для этого.

class SeriousDesignError(Exception):
    pass

Так что вы можете сделать это

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

Я думаю, что это наиболее значимое сообщение об ошибке. Подобные вещи могут возникнуть только из-за ошибок проектирования (или плохого обслуживания, что одно и то же).

4 голосов
/ 03 мая 2009

Это зависит от того, что вы хотите, чтобы ошибка сигнализировала, но я бы использовал словарь в этом случае:

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)
3 голосов
/ 06 апреля 2012

До сих пор я обычно использовал вариант ответа Джона Фухи - но это не совсем правильно, как отмечает Итан:

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 / else есть операторы, отличные от '=='
  • он отделяет проверку утверждения от логики ветвления, а не чередует их - это облегчает чтение и рефакторинг
2 голосов
/ 03 мая 2009

Я иногда так и делаю:

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

Я думаю, что это хорошо говорит читателю кода, что есть только (в данном случае) две возможности, и каковы они. Хотя вы можете привести более описательную ошибку, чем AssertionError.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...