Есть ли проблемы с производительностью или поддержкой кода при использовании
assert
качестве части стандартного кода вместо использования его только для целей отладки?Является
assert x >= 0, 'x is less than zero'
лучше или хуже чем
if x < 0: raise Exception, 'x is less than zero'
Кроме того, есть ли способ установить бизнес-правило, подобное
if x < 0 raise error
тому, которое всегда проверяется без негоtry/except/finally
, если в любое время кодаx
меньше 0 возникает ошибка, как если бы вы установилиassert x < 0
в начале функции где-нибудь внутри функции гдеx
становится меньше 0, исключение возбуждается?
483
assert
.Ответы:
Чтобы можно было автоматически выдавать ошибку, когда x становится меньше нуля во всей функции. Вы можете использовать дескрипторы классов . Вот пример:
источник
Утверждения должны использоваться для проверки условий, которые никогда не должны возникать . Целью является ранний сбой в случае повреждения программы.
Исключения следует использовать для возможных ошибок, и вы почти всегда должны создавать свои собственные классы исключений .
Например, если вы пишете функцию для чтения из файла конфигурации в файл
dict
, неправильное форматирование в файле должно вызвать aConfigurationSyntaxError
, а вы можетеassert
этого не возвращатьNone
.В вашем примере, если
x
это значение, установленное через пользовательский интерфейс или из внешнего источника, лучше использовать исключение.Если
x
установлен только вашим собственным кодом в той же программе, используйте утверждение.источник
assert
содержит неявноеif __debug__
и может быть оптимизировано - как говорится в ответе Джона МиОператоры assert удаляются при оптимизации компиляции . Так что, да, есть как производительность, так и функциональные различия.
Если вы используете
assert
для реализации функциональности приложения, а затем оптимизируете развертывание в рабочей среде, вас будут мучить дефекты «но это работает в dev».См. ПИТОНОПТИМИЗАЦИЯ и -O -OO
источник
raise
Exception
SuspiciousOperation
Exception
Django
bandit
свой код, он предупредит вас об этом.Четыре цели
assert
Предположим, вы работаете над 200 000 строк кода с четырьмя коллегами - Алисой, Берндом, Карлом и Дафни. Они называют ваш код, вы называете их код.
Затем
assert
имеет четыре роли :Сообщите Алисе, Бернду, Карлу и Дафни, что ожидает ваш код.
Предположим, у вас есть метод, который обрабатывает список кортежей, и логика программы может нарушиться, если эти кортежи не являются неизменяемыми:
Это более достоверно, чем эквивалентная информация в документации, и намного проще в обслуживании.
Сообщите компьютеру, что ожидает ваш код.
assert
обеспечивает правильное поведение от вызывающих вашего кода. Если ваш код вызывает код Алисы, а код Бернда - ваш, то без тогоassert
, если в программе происходит сбой в коде Алисы, Бернд может предположить, что это вина Алисы, Алиса расследует и может предположить, что это ваша ошибка, вы расследуете и говорите Бернду, что это на самом деле его. Много работы потеряно.С утверждениями, кто бы ни получил неправильный вызов, они быстро смогут увидеть, что это их вина, а не ваша. Алиса, Бернд, и вам всем это выгодно. Экономит огромное количество времени.
Сообщите читателям своего кода (включая себя), чего достиг ваш код в какой-то момент.
Предположим, у вас есть список записей, и каждая из них может быть чистой (что хорошо) или может быть smorsh, trale, gullup или twinkled (что все неприемлемо). Если это сморш, то должно быть безмятежно; если это trale, это должно быть baludoed; если это гуллуп, то нужно идти рысью (и затем, возможно, тоже ходить); если он мерцает, он должен мигать снова, кроме четверга. Вы поняли: это сложные вещи. Но конечным результатом является (или должно быть), что все записи чисты. Правильная вещь (TM), чтобы сделать, состоит в том, чтобы суммировать эффект Вашей очистки цикла как
Это утверждение избавляет от головной боли всех, кто пытается понять, что же такое замечательный цикл. И наиболее частыми из этих людей, вероятно, будут вы сами.
Сообщите компьютеру, чего достиг ваш код в какой-то момент.
Если вы когда-нибудь забудете пройти запись, нуждающуюся в ней, после рычага, это
assert
спасет ваш день и позволит избежать того, что ваш код сломается, дорогая Дафни намного позже.На мой взгляд,
assert
две цели документации (1 и 3) и защиты (2 и 4) одинаково ценны.Информирование людей может быть даже более ценным, чем информирование компьютера, потому что оно может предотвратить те самые ошибки, которые
assert
нужно поймать (в случае 1), и множество последующих ошибок в любом случае.источник
В дополнение к другим ответам, сами утверждения выдают исключения, но только ошибки AssertionErrors. С утилитарной точки зрения утверждения не подходят для случаев, когда вам нужен точный контроль зерна, над которыми вы ловите исключения.
источник
AssertionErrors
, когда вы в порядке, когда он грубый. На самом деле, вы не должны ловить их.Единственное, что действительно не так с этим подходом, это то, что трудно сделать очень описательное исключение, используя операторы assert. Если вы ищете более простой синтаксис, помните, что вы можете также сделать что-то вроде этого:
Другая проблема заключается в том, что использование assert для обычной проверки условий состоит в том, что затрудняет отключение отладочных утверждений с помощью флага -O.
источник
Слово « утверждать» на английском языке используется в смысле ругаться , утверждать , заявлять . Это не значит «проверить» или «должно быть» . Это означает, что вы как кодер делаете здесь присяжные заявления :
Если код правильный, за исключением сбоев одного события, сбоев оборудования и т. Д., Никакое утверждение никогда не завершится неудачей . Вот почему поведение программы для конечного пользователя не должно быть затронуто. Особенно утверждение не может потерпеть неудачу даже в исключительных программных условиях . Такого просто не бывает. Если это произойдет, программист должен быть зарезан за это.
источник
Как уже было сказано ранее, утверждения следует использовать, когда ваш код НЕ ДОЛЖЕН когда-либо достигать точки, то есть там есть ошибка. Вероятно, наиболее полезная причина, по которой я вижу использование утверждения, - это инвариант / пред / постусловие. Это то, что должно быть верно в начале или конце каждой итерации цикла или функции.
Например, рекурсивная функция (2 отдельные функции, одна из которых обрабатывает неверный ввод, а другая - неверный код, потому что рекурсию трудно отличить). Это сделало бы очевидным, если бы я забыл написать заявление if, что пошло не так.
Эти инварианты цикла часто могут быть представлены с утверждением.
источник
#precondition: n >= 0
чтобы утверждать, он может просто написать@precondition(lambda n: n >= 0)
__doc__
Есть ли проблема с производительностью?
Пожалуйста, не забудьте "заставить это работать сначала, прежде чем заставить это работать быстро" .
Очень мало процентов любой программы обычно имеют отношение к ее скорости. Вы всегда можете выкинуть или упростить,
assert
если это когда-либо окажется проблемой производительности - и большинство из них никогда не будет.Будьте прагматичны :
предположим, что у вас есть метод, который обрабатывает непустой список кортежей, и логика программы сломается, если эти кортежи не являются неизменяемыми. Вы должны написать:
Это, вероятно, хорошо, если ваши списки имеют длину в десять записей, но это может стать проблемой, если в них есть миллион записей. Но вместо того, чтобы полностью отказаться от этого ценного чека, вы можете просто понизить его до
который дешев, но, вероятно, поймает большую часть фактических ошибок в программе в любом случае.
источник
assert(len(listOfTuples)==0 or type(listOfTyples[0])==tuple)
.Что ж, это открытый вопрос, и у меня есть два аспекта, которые я хочу затронуть: когда добавлять утверждения и как писать сообщения об ошибках.
Цель
Чтобы объяснить это новичку - утверждения - это утверждения, которые могут вызвать ошибки, но вы их не поймаете. И их обычно не следует поднимать, но в реальной жизни они все равно иногда поднимаются. И это серьезная ситуация, из которой код не может восстановиться, что мы называем «фатальной ошибкой».
Далее, это для «целей отладки», что, хотя и правильно, звучит очень пренебрежительно. Мне больше нравится формулировка «объявляющие инварианты, которые никогда не следует нарушать», хотя она работает по-разному для разных начинающих ... Некоторые «просто получают это», а другие либо не находят в этом смысла, либо заменяют нормальные исключения, или даже контролировать поток с ним.
Стиль
В Python
assert
это утверждение, а не функция! (помнитеassert(False, 'is true')
, не поднимет. Но, имея это в стороне:Когда и как написать необязательное «сообщение об ошибке»?
Это на самом деле относится к платформам модульного тестирования, которые часто имеют много специальных методов для выполнения утверждений (
assertTrue(condition)
иassertFalse(condition), assertEqual(actual, expected)
т. Д.). Они также часто дают возможность прокомментировать утверждение.В одноразовом коде вы можете обойтись без сообщений об ошибках.
В некоторых случаях нечего добавить к утверждению:
def dump (что-то): утверждение isinstance (что-то, Dumpable) # ...
Но кроме этого, сообщение полезно для общения с другими программистами (которые иногда являются интерактивными пользователями вашего кода, например, в Ipython / Jupyter и т. Д.).
Дайте им информацию, а не только утечки внутренних деталей реализации.
вместо:
записывать:
или, может быть, даже:
Я знаю, я знаю - это не случай для статического утверждения, но я хочу указать на информационную ценность сообщения.
Негативное или позитивное сообщение?
Это может быть спорным, но мне больно читать такие вещи, как:
это две противоречивые вещи, написанные рядом друг с другом. Поэтому, когда бы я ни влиял на кодовую базу, я настаиваю на том, чтобы указать, что мы хотим, используя дополнительные глаголы, такие как «должен» и «должен», а не говорить то, что нам не нужно.
утверждать a == b, 'a должно быть равно b'
Затем получение
AssertionError: a must be equal to b
также читабельно, и выражение выглядит логичным в коде. Кроме того, вы можете получить что-то из этого, не читая трассировку (которая иногда может даже не быть доступной).источник
Как использование, так
assert
и возникновение исключений касаются общения.Утверждения - это утверждения о правильности кода, адресованные разработчикам . Утверждение в коде информирует читателей кода об условиях, которые должны быть выполнены для правильности кода. Утверждение, которое не выполняется во время выполнения, сообщает разработчикам о наличии дефекта в коде, который необходимо исправить.
Исключением являются указания на нестандартные ситуации, которые могут возникать во время выполнения, но не могут быть разрешены с помощью имеющегося кода, адресованного в вызывающем коде, который должен быть там обработан. Возникновение исключения не указывает на наличие ошибки в коде.
Поэтому, если вы рассматриваете возникновение конкретной ситуации во время выполнения как ошибку, о которой вы хотели бы сообщить разработчикам («Привет, разработчик, это условие означает, что где-то есть ошибка, исправьте код».) пойти на утверждение. Если утверждение проверяет входные аргументы вашего кода, вы, как правило, должны добавить в документацию, что ваш код имеет «неопределенное поведение», когда входные аргументы нарушают эти условия.
Если вместо этого возникновение этой самой ситуации не является признаком ошибки в ваших глазах, а вместо этого (возможно, редкой, но) возможной ситуации, которая, по вашему мнению, должна обрабатываться клиентским кодом, создайте исключение. Ситуации, когда возникает исключение, должны быть частью документации соответствующего кода.
Оценка утверждений занимает некоторое время. Однако они могут быть устранены во время компиляции. Это имеет некоторые последствия, однако, см. Ниже.
Обычно утверждения улучшают удобство сопровождения кода, поскольку они улучшают читабельность, делая явные предположения и регулярно проверяя эти предположения во время выполнения. Это также поможет поймать регрессии. Однако следует учитывать одну проблему: выражения, используемые в утверждениях, не должны иметь побочных эффектов. Как уже упоминалось выше, утверждения могут быть устранены во время компиляции - это означает, что потенциальные побочные эффекты также исчезнут. Это может - непреднамеренно - изменить поведение кода.
источник
Утверждение должно проверить -
1. правильное условие,
2. правильное утверждение,
3. истинная логика;
исходного кода. Вместо того, чтобы проваливать весь проект, он дает сигнал, что что-то не подходит в вашем исходном файле.
В примере 1, поскольку переменная 'str' не равна нулю. Таким образом, никакие утверждения или исключения не будут подняты.
Пример 1:
В примере 2 переменная 'str' равна нулю. Таким образом, мы спасаем пользователя от опережающей ошибочной программы оператором assert .
Пример 2:
В тот момент, когда мы не хотим отладки и осознали проблему утверждения в исходном коде. Отключить флаг оптимизации
python -O assertStatement.py
ничего не получит печать
источник
В таких средах разработки, таких как PTVS, PyCharm,
assert isinstance()
операторы Wing могут использоваться для включения завершения кода для некоторых неясных объектов.источник
typing.cast
.Для чего стоит, если вы имеете дело с кодом, который полагается на
assert
правильное функционирование, то добавление следующего кода обеспечит включение утверждений:источник