Ответы:
assert
Утверждение существует практически в каждом языке программирования. Это помогает обнаруживать проблемы в начале вашей программы, где причина ясна, а не позже, как побочный эффект какой-либо другой операции.
Когда вы делаете ...
assert condition
... вы говорите программе проверить это условие и немедленно вызвать ошибку, если условие ложно.
В Python это примерно эквивалентно этому:
if not condition:
raise AssertionError()
Попробуйте это в оболочке Python:
>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
Утверждения могут содержать необязательное сообщение, и вы можете отключить их при запуске интерпретатора.
Чтобы напечатать сообщение, если утверждение не выполнено:
assert False, "Oh no! This assertion failed!"
Вы не использовать скобки для вызова assert
как функции. Это утверждение. Если вы это сделаете, assert(condition, message)
вы будете запускать assert
с (condition, message)
кортежем в качестве первого параметра.
Что касается их отключения, то при работе python
в оптимизированном режиме, где __debug__
есть False
, утверждения assert будут игнорироваться. Просто передайте -O
флаг:
python -O script.py
Смотрите здесь для соответствующей документации.
if not condition: raise AssertError()
, почему я должен использовать assert? Существуют ли условия, при которых утверждение лучше, чем просто более короткая форма if not condition
заявления?
if
). Прочитайте документы для получения дополнительной информации :)
assert
, но после прочтения всех ответов я полностью ничего не получил!
Остерегайтесь скобок. Как уже было отмечено выше, в Python 3, assert
по - прежнему является утверждение , поэтому по аналогии с print(..)
, можно экстраполировать то же самое assert(..)
или , raise(..)
но вы не должны.
Это важно, потому что:
assert(2 + 2 == 5, "Houston we've got a problem")
не будет работать, в отличие от
assert 2 + 2 == 5, "Houston we've got a problem"
Причина, по которой первый не будет работать, состоит в том, что он bool( (False, "Houston we've got a problem") )
оценивается как True
.
В заявлении assert(False)
это просто лишние круглые скобки False
, которые оценивают их содержимое. Но с assert(False,)
круглыми скобками теперь есть кортеж, а непустой кортеж оценивается True
в логическом контексте.
assert (2 + 2 = 5), "Houston we've got a problem"
должно быть хорошо, да?
assert (2 + 2 = 5), "Houston we've got a problem"
не сработает ... но это не имеет ничего общего с утверждением assert, что нормально. Ваше состояние не будет работать, потому что это не условие. Пропустить секунду =
.
Как отмечалось в других ответах, assert
это похоже на создание исключения, если данное условие не соответствует действительности. Важным отличием является то, что операторы assert игнорируются, если вы компилируете свой код с опцией оптимизации -O
. Документация говорит , что assert expression
может быть лучше описано как эквивалент
if __debug__:
if not expression: raise AssertionError
Это может быть полезно, если вы хотите тщательно протестировать свой код, а затем выпустить оптимизированную версию, если вы довольны тем, что ни одно из ваших утверждений не завершилось неудачей - когда включена оптимизация, __debug__
переменная становится ложной, а условия перестают оцениваться. Эта функция также может вас поймать, если вы полагаетесь на утверждения и не понимаете, что они исчезли.
if Not Error: raise Exception(“ this is a error”)
? Таким образом, программа все равно покажет источник ошибки, когда пользователь ее запустит ..
assert
оператор? Здесь предполагается, что когда программа выпущена для конечного пользователя, вы используете флаг -O, таким образом, предполагая, что все ошибки были удалены. Следовательно, любая ошибка или сбой программы происходят из-за ввода в программу, которая действительна в соответствии с контрактом, но не может быть обработана программой. Так что это должно предупредить пользователя как такового.
Цель утверждения в Python - информировать разработчиков о неисправимых ошибках в программе.
Утверждения не предназначены для оповещения об ожидаемых ошибках, например, «файл не найден», где пользователь может предпринять корректирующие действия (или просто повторить попытку).
Другой способ взглянуть на это - сказать, что утверждения - это внутренние самопроверки в вашем коде. Они работают, объявив некоторые условия невозможными в вашем коде. Если эти условия не выполняются, это означает, что в программе есть ошибка.
Если ваша программа не содержит ошибок, эти условия никогда не возникнут. Но если один из них действительно произойдет программа даст сбой с ошибкой утверждение , сообщая вам , какие именно было запущено «невозможно» состояние. Это значительно облегчает поиск и исправление ошибок в ваших программах.
Вот краткое изложение учебника по утверждениям Python, которые я написал:
Инструкция assert Python является средством отладки, а не механизмом обработки ошибок во время выполнения. Цель использования утверждений состоит в том, чтобы позволить разработчикам быстрее находить основную причину ошибки. Ошибка утверждения никогда не должна возникать, если в вашей программе нет ошибки.
assert
заявление и когда использовать это. Я пытаюсь понять ряд терминов, которые вы ввели в статье.
assert store.product_exists(product_id), 'Unknown product id'
это не очень хорошая практика, потому что если отладка отключена, то user
даже если нет admin
, удастся удалить продукт. Считаете ли вы , assert user.is_admin()
как unrecoverable
ошибка? Почему это не так self-check
?
assert statement
, не может ли price
также считаться пользовательским вводом? Почему вы рассматриваете assert user.is_admin()
как проверку данных, а не как assert price
?
Другие уже дали вам ссылки на документацию.
Вы можете попробовать следующее в интерактивной оболочке:
>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
builtins.AssertionError:
Первое утверждение ничего не делает, а второе вызывает исключение. Это первая подсказка: утверждения полезны для проверки условий, которые должны быть истинными в данной позиции вашего кода (обычно начало (предусловия) и конец функции (постусловия)).
Утверждения в действительности тесно связаны с программированием по контракту, что является очень полезной инженерной практикой:
Из документов:
Assert statements are a convenient way to insert debugging assertions into a program
Здесь вы можете прочитать больше: http://docs.python.org/release/2.5.2/ref/assert.html
Утверждения - это систематический способ проверки того, что внутреннее состояние программы соответствует ожидаемому программистом с целью выявления ошибок. Смотрите пример ниже.
>>> number = input('Enter a positive number:')
Enter a positive number:-1
>>> assert (number > 0), 'Only positive numbers are allowed!'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Only positive numbers are allowed!
>>>
Вот простой пример, сохраните это в файле (скажем, b.py)
def chkassert(num):
assert type(num) == int
chkassert('a')
и результат, когда $python b.py
Traceback (most recent call last):
File "b.py", line 5, in <module>
chkassert('a')
File "b.py", line 2, in chkassert
assert type(num) == int
AssertionError
если оператор после assert равен true, то программа продолжается, но если оператор после assert равен false, программа выдает ошибку. Просто как тот.
например:
assert 1>0 #normal execution
assert 0>1 #Traceback (most recent call last):
#File "<pyshell#11>", line 1, in <module>
#assert 0>1
#AssertionError
assert
Утверждение существует практически в каждом языке программирования. Это помогает обнаруживать проблемы в начале вашей программы, где причина ясна, а не позже, как побочный эффект какой-либо другой операции. Они всегда ожидаютTrue
условия.
Когда вы делаете что-то вроде:
assert condition
Вы говорите программе проверить это условие и немедленно вызвать ошибку, если она ложна.
В Python assert
выражение эквивалентно:
if __debug__:
if not <expression>: raise AssertionError
Вы можете использовать расширенное выражение для передачи необязательного сообщения :
if __debug__:
if not (expression_1): raise AssertionError(expression_2)
Попробуйте это в интерпретаторе Python:
>>> assert True # Nothing happens because the condition returns a True value.
>>> assert False # A traceback is triggered because this evaluation did not yield an expected value.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
Есть некоторые предостережения видели перед их использованием в основном для тех , кто посчитает переключение между assert
и if
отчетностью. Целью assert
является использование в случаях, когда программа проверяет условие и возвращает значение, которое должно немедленно остановить программу, вместо того, чтобы использовать какой-либо альтернативный способ обойти ошибку:
Как вы могли заметить, в этом assert
утверждении используются два условия. Следовательно, не используйте скобки, чтобы использовать их как очевидный совет. Если вы делаете такие как:
assert (condition, message)
Пример:
>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
Вы будете запускать assert
с, (condition, message)
который представляет кортеж в качестве первого параметра, и это происходит потому, что непустой кортеж в Python всегдаTrue
. Тем не менее, вы можете сделать отдельно без проблем:
assert (condition), "message"
Пример:
>>> assert (1==2), ("This condition returns a %s value.") % "False"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: This condition returns a False value.
Если вам интересно, когда использовать assert
заявление. Возьмите пример, используемый в реальной жизни:
* Когда ваша программа стремится контролировать каждый параметр, введенный пользователем или что-то еще:
def loremipsum(**kwargs):
kwargs.pop('bar') # return 0 if "bar" isn't in parameter
kwargs.setdefault('foo', type(self)) # returns `type(self)` value by default
assert (len(kwargs) == 0), "unrecognized parameter passed in %s" % ', '.join(kwargs.keys())
* Другой случай по математике, когда 0 или не положительный, как коэффициент или константа для определенного уравнения:
def discount(item, percent):
price = int(item['price'] * (1.0 - percent))
print(price)
assert (0 <= price <= item['price']),\
"Discounted prices cannot be lower than 0 "\
"and they cannot be higher than the original price."
return price
* или даже простой пример логической реализации:
def true(a, b):
assert (a == b), "False"
return 1
def false(a, b):
assert (a != b), "True"
return 0
Крайне важно не полагаться на assert
оператор для выполнения обработки данных или проверки данных, поскольку этот оператор можно отключить при инициализации Python с помощью -O
или -OO
флага (означающего соответственно значения 1, 2 и 0 (по умолчанию)) или PYTHONOPTIMIZE
переменной среды ,
Значение 1:
* утверждения отключены;
* файлы байт-кода генерируются с использованием .pyo
расширения вместо .pyc
;
* sys.flags.optimize
установлено в 1 ( True
);
* и, __debug__
установлен в False
;
Значение 2: отключает еще один материал
* строки документов отключены;
Следовательно, использование этого assert
оператора для проверки ожидаемых данных чрезвычайно опасно, что подразумевает даже некоторые проблемы безопасности. Затем, если вам нужно подтвердить какое-то разрешение, я рекомендую вам raise AuthError
вместо этого. В качестве предварительного условия, assert
обычно используется программистами в библиотеках или модулях, которые не имеют прямого взаимодействия с пользователем.
Как кратко изложено на C2 Wiki :
Утверждение - это логическое выражение в определенной точке программы, которое будет истинным, если в программе нет ошибки.
Вы можете использовать assert
оператор для документирования вашего понимания кода в конкретной точке программы. Например, вы можете задокументировать предположения или гарантии относительно входных данных (предварительных условий), состояния программы (инвариантов) или выходных данных (постусловий).
Если ваше утверждение когда-либо окажется неудачным, это предупреждение для вас (или вашего преемника), что вы неправильно поняли программу, когда вы ее написали, и что она, вероятно, содержит ошибку.
Для получения дополнительной информации у Джона Регера есть замечательное сообщение в блоге об использовании утверждений , которое также применимо к assert
выражению Python .
Python assert - это, по сути, средство отладки, которое проверяет условия для внутренней самопроверки вашего кода. Assert делает отладку действительно простой, когда ваш код попадает в невозможные крайние случаи. Утверждают, проверяют эти невозможные случаи.
Допустим, есть функция для расчета цены товара после скидки:
def calculate_discount(price, discount):
discounted_price = price - [discount*price]
assert 0 <= discounted_price <= price
return discounted_price
Здесь discounts_price никогда не может быть меньше 0 и больше фактической цены. Таким образом, в случае нарушения вышеуказанного условия assert вызывает ошибку утверждения, которая помогает разработчику определить, что произошло нечто невозможное.
Надеюсь, поможет :)
assert
полезен в контексте отладки, но не следует полагаться вне контекста отладки.
Мое краткое объяснение:
assert
Возникает, AssertionError
если выражение ложно, в противном случае просто продолжает код, и если есть запятая, какой бы она ни была AssertionError: whatever after comma
, и код будет выглядеть так:raise AssertionError(whatever after comma)
Связанный учебник об этом:
https://www.tutorialspoint.com/python/assertions_in_python.htm
assert
, но не когда использовать (или не использовать) assert
; также отмечая, что assert
можно отключить, если__debug__
это False
было бы полезно.
В Pycharm, если вы используете assert
вместе с isinstance
объявлением типа объекта, он позволит вам получить доступ к методам и атрибутам родительского объекта во время кодирования, он автоматически завершится автоматически.
Например, скажем self.object1.object2
, это MyClass
объект.
import MyClasss
def code_it(self):
testObject = self.object1.object2 # at this point, program doesn't know that testObject is a MyClass object yet
assert isinstance(testObject , MyClasss) # now the program knows testObject is a MyClass object
testObject.do_it() # from this point on, PyCharm will be able to auto-complete when you are working on testObject
Как написано в других ответах, assert
операторы используются для проверки состояния программы на данный момент.
Я не буду повторять то, что было сказано о связанном сообщении, скобках или -O
опции и __debug__
константе. Проверьте также документ для получения информации из первых рук. Я сосредоточусь на вашем вопросе: какая польза assert
? Точнее, когда (а когда нет) следует использовать assert
?
Операторы assert
полезны для отладки программы, но не рекомендуется проверять ввод пользователя. Я использую следующее эмпирическое правило: сохраняйте утверждения, чтобы обнаружить, что это не должно случиться . Пользовательский ввод может быть неправильным, например, пароль слишком короткий, но это не так . Если диаметр круга не в два раза больше его радиуса, то у вас такого не должно быть .
Самое интересное, на мой взгляд, использование assert
вдохновлено
программированием по контракту, как описано Б. Мейером в [Создание объектно-ориентированного программного обеспечения] (
https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction% 2C_2nd_Edition
) и реализован на [языке программирования Eiffel] (
https://en.wikipedia.org/wiki/Eiffel_(programming_language) ). Вы не можете полностью эмулировать программирование по контракту, используя assert
оператор, но интересно сохранить намерение.
Вот пример. Представьте, что вам нужно написать head
функцию (например, [ head
функция в Haskell] (
http://www.zvon.org/other/haskell/Outputprelude/head_f.html )). Вам дана следующая спецификация: «если список не пустой, вернуть первый элемент списка». Посмотрите на следующие реализации:
>>> def head1(xs): return xs[0]
А также
>>> def head2(xs):
... if len(xs) > 0:
... return xs[0]
... else:
... return None
(Да, это можно записать как return xs[0] if xs else None
, но это не главное) .
Если список не пустой, обе функции имеют одинаковый результат, и этот результат является правильным:
>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True
Следовательно, обе реализации являются (я надеюсь) правильными. Они отличаются, когда вы пытаетесь взять заголовок пустого списка:
>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range
Но:
>>> head2([]) is None
True
Опять же, обе реализации верны, потому что никто не должен передавать пустой список этим функциям (мы не в спецификации ). Это неправильный вызов, но если вы сделаете такой вызов, все может произойти. Одна функция вызывает исключение, другая возвращает специальное значение. Самое главное: мы не можем полагаться на это поведение . Если xs
пусто, это будет работать:
print(head2(xs))
Но это приведет к сбою программы:
print(head1(xs))
Чтобы избежать неожиданностей, я хотел бы знать, когда я передаю какой-то неожиданный аргумент в функцию. Другими словами: я хотел бы знать, когда наблюдаемое поведение ненадежно, потому что оно зависит от реализации, а не от спецификации. Конечно, я могу прочитать спецификацию, но программисты не всегда внимательно читают документы.
Представьте, если бы у меня был способ вставить спецификацию в код, чтобы получить следующий эффект: когда я нарушаю спецификацию, например, передавая пустой список head
, я получаю предупреждение. Это было бы очень полезно для написания правильной (то есть соответствующей спецификации) программы. И вот где assert
на сцене появляется:
>>> def head1(xs):
... assert len(xs) > 0, "The list must not be empty"
... return xs[0]
А также
>>> def head2(xs):
... assert len(xs) > 0, "The list must not be empty"
... if len(xs) > 0:
... return xs[0]
... else:
... return None
Теперь у нас есть:
>>> head1([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
А также:
>>> head2([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
Обратите внимание, что head1
бросает AssertionError
, а не IndexError
. Это важно, потому что это AssertionError
не какая-либо ошибка во время выполнения: она сигнализирует о нарушении спецификации. Я хотел предупреждение, но я получаю ошибку. К счастью, я могу отключить проверку (используя -O
опцию), но на свой страх и риск. Я сделаю это, крушение действительно дорого, и надеюсь на лучшее. Представьте, что моя программа встроена в космический корабль, который путешествует через черную дыру. Я отключу утверждения и надеюсь, что программа достаточно надежна, чтобы не зависать как можно дольше.
Этот пример касался только предварительных условий, которые можно использовать assert
для проверки постусловий (возвращаемое значение и / или состояние) и инвариантов (состояние класса). Обратите внимание, что проверка постусловий и инвариантов с помощью assert
может быть громоздкой:
У вас не будет чего-то более сложного, чем у Eiffel, но вы можете улучшить общее качество программы.
Подводя итог, assert
можно сказать , что это удобный способ обнаружения ситуации, которая не должна возникать . Нарушения спецификации (например, передача пустого списка head
) являются первоклассными, это не должно происходить в ситуациях. Следовательно, хотя assert
оператор может использоваться для обнаружения любой непредвиденной ситуации, это привилегированный способ обеспечить выполнение спецификации. После того, как вы вставили assert
операторы в код для представления спецификации, мы можем надеяться, что вы улучшили качество программы, потому что будут сообщаться неверные аргументы, неправильные возвращаемые значения, неправильные состояния класса ....
format: assert Expression [, arguments] Когда assert встречает оператор, Python оценивает выражение. Если оператор не равен true, возникает исключение (assertionError). Если утверждение не выполняется, Python использует ArgumentExpression в качестве аргумента для AssertionError. Исключения AssertionError могут быть перехвачены и обработаны, как и любое другое исключение, с помощью оператора try-exception, но если не обработано, они завершат программу и произведут трассировку. Пример:
def KelvinToFahrenheit(Temperature):
assert (Temperature >= 0),"Colder than absolute zero!"
return ((Temperature-273)*1.8)+32
print KelvinToFahrenheit(273)
print int(KelvinToFahrenheit(505.78))
print KelvinToFahrenheit(-5)
Когда приведенный выше код выполняется, он дает следующий результат:
32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print KelvinToFahrenheit(-5)
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!
def getUser(self, id, Email):
user_key = id and id or Email
assert user_key
Может использоваться для обеспечения передачи параметров в вызове функции.
if not user_key: raise ValueError()
последних двух абзацев здесь: wiki.python.org/moin/UsingAssertionsEffectively
assert
Не следует использовать для проверки входных данных , поскольку либо проверки будут удалены, если __debug__
естьFalse
. Кроме того, использование утверждений в целях, не связанных с отладкой, может привести к тому AssertionError
, что люди поймут получающиеся s, что может сделать отладку более сложной, а не меньшей.
>>>this_is_very_complex_function_result = 9
>>>c = this_is_very_complex_function_result
>>>test_us = (c < 4)
>>> #first we try without assert
>>>if test_us == True:
print("YES! I am right!")
else:
print("I am Wrong, but the program still RUNS!")
I am Wrong, but the program still RUNS!
>>> #now we try with assert
>>> assert test_us
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
assert test_us
AssertionError
>>>
По сути, ключевое слово assert означает, что если условие не истинно, то оно через ошибку assertionerror, иначе оно продолжается, например, в python.
код-1
a=5
b=6
assert a==b
ВЫВОД:
assert a==b
AssertionError
код-2
a=5
b=5
assert a==b
ВЫВОД:
Process finished with exit code 0
assert
, но не отвечает, когда использовать (или не использовать) assert
.