2012-03-08 5 views
6

В последнее время я добавлял asserts почти к каждой отдельной функции, которую я делаю, чтобы проверять каждый вход как недобросовестную замену для проверки типа или для предотвращения случайного ввода некорректных данных во время разработки. Например,У вас слишком много утверждений (в Python)?

def register_symbol(self, symbol, func, keypress=None): 
    assert(isinstance(symbol, basestring)) 
    assert(len(symbol) == 1) 
    assert(callable(func)) 
    assert(keypress is None or type(keypress) is int) 
    self.symbols_map[symbol] = (func, keypress) 
    return 

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

+0

Сторона примечания: вы должны использовать утиную печать (не проверяйте тип, проверяйте «способности», как доступные методы). Кроме того, это 'return' совершенно не нужно. –

+1

Реальный вопрос: помогает ли это вам или затрудняет вашу работу. Если множество утверждений поможет вам отслеживать ошибки - сделайте много утверждений в своем коде. Если вам нужна статическая типизация, почему вы выбрали Python для своего проекта? –

+3

@ Никлас Мне нравится возвращение. Это делает меня счастливым внутри: D – Michael0x2a

ответ

7

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

assert(callable(func)) 

может быть примером для такого утверждают - если func не отозваны, вы получите сообщение об ошибке в совершенно другой строке кода, чем когда фактическая ошибка, и она не может быть очевидным, как не вызываемый объект оказался в self.symbols_map. Я пишу «могу», потому что это зависит от остальной части вашего кода - если это единственное место, где обновляется self.symbols_map, утверждение также может быть ненужным.

Первый и последний утверждают, безусловно, против идеи утиного ввода, , а второй избыточен. Если symbol не является строкой длины 1, скорее всего, self.symbols_map[symbol] в любом случае поднимет KeyError, так что нет необходимости в утверждениях.

Последние утверждают, тоже неправильно - type(keypress) не может быть None и проверка типа должна быть сделана с isinstance(). Там могут быть очень специализированные приложения, где вы не можете разрешать подтипы, но проверка должна выполняться с помощью type(x) is int вместо type(x) == int. Проверка на None должна производиться по x is None, а не по type(x) is NoneType.

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

+0

Упс, извините. Я исправлю последнее утверждение. – Michael0x2a

+0

Hm, если 'symbols_map' является dict, он не должен поднимать' KeyError'. –

+0

@NiklasB .: Не могли бы вы объяснить это чуть дальше? –

3

Аппетиты в вашем коде не так полезны, как unittests. Сделайте больше из последних, меньше из первых.

2

Помните, что утверждения assert удаляются, когда Python генерирует оптимизированный байт-код! Так как это имеет место в большинстве производственных сред, утверждения assert не могут использоваться для проверки ввода. На самом деле я пришел к выводу, что я не могу использовать их ни для чего, если я не могу полагаться на их исполнение. Поэтому, если мне нужно проверить какое-то условие, вместо этого я использую «if ... raise ...», и если я просто хочу проверить свой код, я пишу unittests.

Смежные вопросы