Відповіді:
The 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
, заяви твердження будуть ігноруватися. Просто передайте -O
прапор:
python -O script.py
Дивіться тут відповідну документацію.
if not condition: raise AssertError()
, чому я маю використовувати ствердження? Чи існують умови, за яких аргумент кращий, ніж просто коротша форма 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
подібне до викидання винятку, якщо задана умова не відповідає дійсності. Важлива відмінність полягає в тому, що твердження про ствердження ігноруються, якщо ви компілюєте код з опцією оптимізації -O
. Документація каже , що assert expression
може бути краще описано як еквівалент
if __debug__:
if not expression: raise AssertionError
Це може бути корисно, якщо ви хочете ретельно протестувати свій код, а потім випустіть оптимізовану версію, коли ви щасливі, що жоден із ваших випадків твердження не виходить - коли оптимізація ввімкнена, __debug__
змінна стає помилковою і умови перестануть оцінюватися. Ця функція також може вас застати, якщо ви покладаєтесь на твердження і не розумієте, що вони зникли.
if Not Error: raise Exception(“ this is a error”)
? Таким чином, програма все одно покаже джерело помилки, коли користувач її запустить ..
assert
заяву? Припущення тут полягає в тому, що коли програма випускається кінцевому користувачеві, ви використовуєте прапор -O, при цьому припускаючи, що всі помилки були видалені. Отже, будь-яка помилка або збій програми відбувається через вхід до програми, що діє згідно з договором, але не може бути оброблена програмою. Тому він повинен насторожити користувача як такого.
Метою твердження в Python є інформування розробників про неповернення помилки в програмі.
Твердження не призначені для сигналізації очікуваних умов помилки, наприклад, "файл не знайдено", коли користувач може вжити коригувальних дій (або просто спробувати ще раз).
Ще один спосіб поглянути на це - сказати, що твердження - це внутрішня самоперевірка вашого коду. Вони працюють, оголошуючи деякі умови неможливими у вашому коді. Якщо ці умови не виконуються, це означає, що в програмі є помилка.
Якщо у вашій програмі немає помилок, ці умови ніколи не виникнуть. Але якщо один з них дійсно станеться програма дасть збій з помилкою твердження , повідомляючи вам , які саме було запущено «неможливо» стан. Це значно простіше відстежувати та виправляти помилки у ваших програмах.
Ось підсумок із підручника про твердження Python, які я написав:
Заява твердження 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 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)
символом a, який представляє кортеж як перший параметр, і це трапляється, тому що не порожній кортеж у 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
зазвичай використовують програмісти в бібліотеках або модулях, у яких користувач не взаємодіє безпосередньо.
Як коротко узагальнено у Вікі С2 :
Затвердження - булевий вираз у певній точці програми, що буде істинним, якщо не буде помилки в програмі.
Ви можете використовувати assert
оператор, щоб документувати своє розуміння коду в певному програмному пункті. Наприклад, ви можете задокументувати припущення або гарантії щодо входів (передумов), стану програми (інваріанти) або виходів (постумов).
Якщо ваше твердження коли-небудь не вдасться, це попередження для вас (або вашого наступника) про те, що ваше розуміння програми було неправильним, коли ви її написали, і що вона, ймовірно, містить помилку.
Для отримання додаткової інформації у Джона Регера є чудова публікація в блозі про використання тверджень , що стосується також і assert
заяви Python .
Python assert - це в основному налагоджувальний засіб, який перевіряє умову для внутрішньої самоперевірки вашого коду. Assert робить налагодження дійсно простим, коли ваш код потрапляє у неможливі крайові випадки. Затвердити перевірку цих неможливих випадків.
Скажімо, існує функція розрахунку ціни товару після знижки:
def calculate_discount(price, discount):
discounted_price = price - [discount*price]
assert 0 <= discounted_price <= price
return discounted_price
тут, знижена_ціна ніколи не може бути меншою від 0 і більшою від фактичної ціни. Так, у випадку порушення вищезазначеної умови ствердження викликає помилку твердження, яка допомагає розробнику визначити, що сталося щось неможливе.
Сподіваюся, це допомагає :)
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
) та впроваджено в [Ейфелева мова програмування] (
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
кидає an AssertionError
, а не an IndexError
. Це важливо, оскільки ан AssertionError
- це не будь-яка помилка виконання: вона сигналізує про порушення специфікації. Я хотів попередження, але отримую помилку. На щастя, я можу відключити перевірку (використовуючи -O
опцію), але на свій страх і ризик. Я зроблю це крахом дійсно дорого, і сподіваюся на краще. Уявіть, що моя програма вбудована в космічний корабель, який подорожує чорною дірою. Я відключу твердження і сподіваюся, що програма є достатньо надійною, щоб не виходити з ладу якомога довше.
Цей приклад стосувався лише передумов, якщо ви можете використовувати assert
для перевірки постумов (повернене значення та / або стан) та інваріантів (стан класу). Зауважте, що перевірка постконвенцій та інваріантів за допомогою assert
може бути громіздкою:
У вас не буде щось настільки витончене, як Ейфелева, але ви все ж можете покращити загальну якість програми.
Підводячи підсумок, assert
твердження є зручним способом виявлення такої ситуації, яка не повинна відбуватися . Порушення специфікації (наприклад, передача порожнього списку head
) є першим класом, цього не повинно відбуватися . Отже, хоча assert
заява може використовуватися для виявлення будь-якої несподіваної ситуації, це привілейований спосіб забезпечити виконання специфікації. Після того, як ви вставили assert
в код заяви для представлення специфікації, ми можемо сподіватися, що ви покращили якість програми, оскільки повідомляться про неправильні аргументи, неправильні значення повернення, неправильні стани класу ...
формат: assert Вираз [, аргументи] Коли assert стикається з твердженням, Python оцінює вираз. Якщо твердження не відповідає дійсності, виникає виняток (assertionError). Якщо твердження не вдалося, Python використовує ArgumentExpression як аргумент для AssertionError. Винятки AssertionError можна виловлювати та обробляти, як і будь-який інший виняток, використовуючи оператор try-osim, але якщо їх не обробляти, вони припиняють програму і видають прослідкування. Приклад:
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()
пунктом Перевірити останні 2 пункти тут: wiki.python.org/moin/UsingAssertionsEffectively
assert
не слід використовувати для перевірки введення, тому що або перевірка буде знята, якщо __debug__
є False
. Також використання тверджень для невиправних цілей може призвести до того AssertionError
, що люди зможуть наздогнати результат , що може ускладнити налагодження замість менше.
>>>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 полягає в тому, що якщо умова не відповідає дійсності, то це через стверджувального помилки, інакше воно продовжується, наприклад, у 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
.