1430

What does assert mean? How is it used?

dreftymac
  • 31,404
  • 26
  • 119
  • 182
Hossein
  • 40,161
  • 57
  • 141
  • 175

23 Answers23

1662

The assert statement exists in almost every programming language. It has two main uses:

  1. It helps detect problems early in your program, where the cause is clear, rather than later when some other operation fails. A type error in Python, for example, can go through several layers of code before actually raising an Exception if not caught early on.

  2. It works as documentation for other developers reading the code, who see the assert and can confidently say that its condition holds from now on.

When you do...

assert condition

... you're telling the program to test that condition, and immediately trigger an error if the condition is false.

In Python, it's roughly equivalent to this:

if not condition:
    raise AssertionError()

Try it in the Python shell:

>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

Assertions can include an optional message, and you can disable them when running the interpreter.

To print a message if the assertion fails:

assert False, "Oh no! This assertion failed!"

Do not use parenthesis to call assert like a function. It is a statement. If you do assert(condition, message) you'll be running the assert with a (condition, message) tuple as first parameter.

As for disabling them, when running python in optimized mode, where __debug__ is False, assert statements will be ignored. Just pass the -O flag:

python -O script.py

See here for the relevant documentation.

salezica
  • 74,081
  • 25
  • 105
  • 166
  • 19
    The purpose of assertions are frequently misunderstood. They are not for early test conditions as has been suggested, and they are not syntactic sugar for test expressions. Their purpose is to "assert" that certain conditions are true at certain points in the program, with the intent of helping programmers understand the state of the system at those points. For example, if at the top of a function I see an "assert arg" statement, then I will know without a doubt that (arg is None) is an invalid state for any subsequent statements in that function, reducing the state set I have to consider. – dhinson919 Jul 08 '21 at 16:46
  • A comment to paraphrase the comment above that assert is a comment. Assert can be used/misused for various goals. It can be used to express a predicate to code. It would be faulty to assume that *arg is None*. It will only be triggered if a path takes the code there with *arg is None*. There can be cases that are not found during test and due to code updates and no 'formal verification' where the predicate arg is not valid. So, it is good evidence of intent. However, **I will know without a doubt** is patently false like `__debug__`. – artless noise Jan 12 '23 at 17:35
601

Watch out for the parentheses. As has been pointed out in other answers, in Python 3, assert is still a statement, so by analogy with print(..), one may extrapolate the same to assert(..) or raise(..) but you shouldn't.

This is wrong:

assert(2 + 2 == 5, "Houston we've got a problem")

This is correct:

assert 2 + 2 == 5, "Houston we've got a problem"

The reason the first one will not work is that bool( (False, "Houston we've got a problem") ) evaluates to True.

In the statement assert(False), these are just redundant parentheses around False, which evaluate to their contents. But with assert(False,) the parentheses are now a tuple, and a non-empty tuple evaluates to True in a boolean context.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Evgeni Sergeev
  • 22,495
  • 17
  • 107
  • 124
  • 8
    Don't forget that people often use parentheses for PEP 8-compliant implicit line continuation Also Also don't forget that tuples are not defined by parentheses but by the existence of the comma (tuples have nothing to do with parens except for the purposes of operator precedence). – cowbert Aug 27 '17 at 20:42
  • 1
    @superbeck One reason that assert might still not use parenthesis even though print now does is because it is *not* a function. In python, function arguments are always evaluated. For example, if you write `foo(5,6,bar(7))`, `bar(7)` is evaluated even if you didn't end up using it. However, in `assert True, bar(7)`, bar(7) is not evaluated because the assertion didn't happen. Using the non-function syntax makes this more obvious, just like how `a = foo(b) if c else bar(d)` will only evaluate `foo` or `bar`, not both. This is sometimes called a "special form". – Eyal Oct 04 '21 at 17:06
184

As other answers have noted, assert is similar to throwing an exception if a given condition isn't true. An important difference is that assert statements get ignored if you compile your code with the optimization option -O. The documentation says that assert expression can better be described as being equivalent to

if __debug__:
   if not expression: raise AssertionError

This can be useful if you want to thoroughly test your code, then release an optimized version when you're happy that none of your assertion cases fail - when optimization is on, the __debug__ variable becomes False and the conditions will stop getting evaluated. This feature can also catch you out if you're relying on the asserts and don't realize they've disappeared.

Ricardo Stuven
  • 4,704
  • 2
  • 34
  • 36
Neil Vass
  • 5,251
  • 2
  • 22
  • 25
103

The goal of an assertion in Python is to inform developers about unrecoverable errors in a program.

Assertions are not intended to signal expected error conditions, like “file not found”, where a user can take corrective action (or just try again).

Another way to look at it is to say that assertions are internal self-checks in your code. They work by declaring some conditions as impossible in your code. If these conditions don’t hold that means there’s a bug in the program.

If your program is bug-free, these conditions will never occur. But if one of them does occur the program will crash with an assertion error telling you exactly which “impossible” condition was triggered. This makes it much easier to track down and fix bugs in your programs.

Here’s a summary from a tutorial on Python’s assertions I wrote:

Python’s assert statement is a debugging aid, not a mechanism for handling run-time errors. The goal of using assertions is to let developers find the likely root cause of a bug more quickly. An assertion error should never be raised unless there’s a bug in your program.

dbader
  • 10,081
  • 2
  • 22
  • 17
56

Others have already given you links to documentation.

You can try the following in a interactive shell:

>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
builtins.AssertionError:

The first statement does nothing, while the second raises an exception. This is the first hint: asserts are useful to check conditions that should be true in a given position of your code (usually, the beginning (preconditions) and the end of a function (postconditions)).

Asserts are actually highly tied to programming by contract, which is a very useful engineering practice:

http://en.wikipedia.org/wiki/Design_by_contract.

pyrrhic
  • 1,769
  • 2
  • 15
  • 27
Baltasarq
  • 12,014
  • 3
  • 38
  • 57
24

From docs:

Assert statements are a convenient way to insert debugging assertions into a program

You can read more here: http://docs.python.org/release/2.5.2/ref/assert.html

binaryfunt
  • 6,401
  • 5
  • 37
  • 59
gruszczy
  • 40,948
  • 31
  • 128
  • 181
21

The assert statement has two forms.

The simple form, assert <expression>, is equivalent to

if __​debug__:
    if not <expression>: raise AssertionError

The extended form, assert <expression1>, <expression2>, is equivalent to

if __​debug__:
    if not <expression1>: raise AssertionError(<expression2>)
Ian Goldby
  • 5,609
  • 1
  • 45
  • 81
Bohdan
  • 16,531
  • 16
  • 74
  • 68
18

Assertions are a systematic way to check that the internal state of a program is as the programmer expected, with the goal of catching bugs. See the example below.

>>> 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!
>>> 
Jacob Abraham
  • 915
  • 9
  • 8
9

What does assert mean? How is it used?

There are great answers here, but not to the second part of the question. Despite many years of practical experience, I only understood the purpose of asserts recently.

Others have already explained how assert is used, so I am super brief. This is how you use it:

assert condition, "error message"

And do not use parentheses, assert is a keyword, not a function.

assert (condition, "error message")  # wrong: this never fails!

A good explanation of how to use assert is given here: http://wiki.c2.com/?WhatAreAssertions The point of assert is to declare invariants in your code. An invariant is a condition that should never be violated unless there is a bug in the code. Think of them as executable documentation. This is deeply connected to how object-oriented programming encapsulates code from the outside world.

In plain English: You should use an assert like a comment in your code for other developers. But it is better than a comment, the "comment" is actually checked in debug mode! If your program cannot be expected to work correctly if the assert is removed, you are using it wrong. In fact, Python will ignore all asserts if you turn on optimizations (python -O). So don't rely on them to be there. In particular, do not use asserts to validate user input. Raise exceptions instead.

Here is a nice example to tie it all together. Let's assume you want to have a special number class in your code which represents positive integers called PositiveInt. Why would you want that? You have many functions that use positive integers as parameters. By using PositiveInt in your code, you don't have to check again and again in every function whether the input is valid. It is guaranteed by PositiveInt. A crude implementation looks like this

class PositiveInt(int):
    # int is immutable, so we have to override new and not init
    def __new__(cls, value):
        if value <= 0:
            raise ValueError(f"{value} is not positive")
        assert value > 0, "value must be positive"
        return super(PositiveInt, cls).__new__(cls, value)   

As you can see, I use both an if ...: raise ... for input validation and an assert at the end of the function. This seems superfluous, but only in this trivial example! Imagine that the function is a bit longer and more complex, so it is not obvious that you have validated the input correctly. The assert at the end makes sure that a bug in your validation code is detected. It also makes the intend of the validation code clear to another programmer, more so than a simple comment.

In summary: use assert like a comment. Use it everywhere! It is cheap and if it ever becomes a performance problem for your users, you can turn it off in releases with python -O.

olq_plo
  • 1,002
  • 10
  • 18
8

Here is a simple example, save this in file (let's say b.py)

def chkassert(num):
    assert type(num) == int


chkassert('a')

and the result when $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
Gaurav Agarwal
  • 18,754
  • 29
  • 105
  • 166
8

As summarized concisely on the C2 Wiki:

An assertion is a boolean expression at a specific point in a program which will be true unless there is a bug in the program.

You can use an assert statement to document your understanding of the code at a particular program point. For example, you can document assumptions or guarantees about inputs (preconditions), program state (invariants), or outputs (postconditions).

Should your assertion ever fail, this is an alert for you (or your successor) that your understanding of the program was wrong when you wrote it, and that it likely contains a bug.

For more information, John Regehr has a wonderful blog post on the Use of Assertions, which applies to the Python assert statement as well.

avandeursen
  • 8,458
  • 3
  • 41
  • 51
8

The assert statement exists in almost every programming language. It helps detect problems early in your program, where the cause is clear, rather than later as a side-effect of some other operation. They always expect a True condition.

When you do something like:

assert condition

You're telling the program to test that condition and immediately trigger an error if it is false.

In Python, assert expression, is equivalent to:

if __debug__:
    if not <expression>: raise AssertionError

You can use the extended expression to pass an optional message:

if __debug__:
    if not (expression_1): raise AssertionError(expression_2)

Try it in the Python interpreter:

>>> 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

There are some caveats to seen before using them mainly for those who deem to toggles between the assert and if statements. The aim to use assert is on occasions when the program verifies a condition and return a value that should stop the program immediately instead of taking some alternative way to bypass the error:

1. Parentheses

As you may have noticed, the assert statement uses two conditions. Hence, do not use parentheses to englobe them as one for obvious advice. If you do such as:

assert (condition, message)

Example:

>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?

You will be running the assert with a (condition, message) which represents a tuple as the first parameter, and this happens cause non-empty tuple in Python is always True. However, you can do separately without problem:

assert (condition), "message"

Example:

>>> 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.

2. Debug purpose

If you are wondering regarding when use assert statement. Take an example used in real life:

* When your program tends to control each parameter entered by the user or whatever else:

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())

* Another case is on math when 0 or non-positive as a coefficient or constant on a certain equation:

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

* or even a simple example of a boolean implementation:

def true(a, b):
    assert (a == b), "False"
    return 1

def false(a, b):
    assert (a != b), "True"
    return 0

3. Data processing or data validation

The utmost importance is to not rely on the assert statement to execute data processing or data validation because this statement can be turned off on the Python initialization with -O or -OO flag – meaning value 1, 2, and 0 (as default), respectively – or PYTHONOPTIMIZE environment variable.

Value 1:

* asserts are disabled;

* bytecode files are generated using .pyo extension instead of .pyc;

* sys.flags.optimize is set to 1 (True);

* and, __debug__ is set to False;

Value 2: disables one more stuff

* docstrings are disabled;

Therefore, using the assert statement to validate a sort of expected data is extremely dangerous, implying even to some security issues. Then, if you need to validate some permission I recommend you raise AuthError instead. As a preconditional effective, an assert is commonly used by programmers on libraries or modules that do not have a user interact directly.

slayer
  • 214
  • 4
  • 11
7

if the statement after assert is true then the program continues , but if the statement after assert is false then the program gives an error. Simple as that.

e.g.:

assert 1>0   #normal execution
assert 0>1   #Traceback (most recent call last):
             #File "<pyshell#11>", line 1, in <module>
             #assert 0>1
             #AssertionError
Shawn Mehan
  • 4,513
  • 9
  • 31
  • 51
abe312
  • 2,547
  • 25
  • 16
7

In Pycharm, if you use assert along with isinstance to declare an object's type, it will let you access the methods and attributes of the parent object while you are coding, it will auto-complete automatically.

For example, let's say self.object1.object2 is a MyClass object.

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
alwbtc
  • 28,057
  • 62
  • 134
  • 188
  • In a similar vein, I find `assert isinstance(obj, ExpectedType)` to be quite useful to inform `mypy` type checking, e.g. to resolve ambiguity in situations where `obj` would otherwise be a `Union[ExpectedType, OtherType]`. – A Real Live Operator Dec 07 '22 at 22:31
3

If you ever want to know exactly what a reserved function does in python, type in help(enter_keyword)

Make sure if you are entering a reserved keyword that you enter it as a string.

rassa45
  • 3,482
  • 1
  • 29
  • 43
3

Python assert is basically a debugging aid which test condition for internal self-check of your code. Assert makes debugging really easy when your code gets into impossible edge cases. Assert check those impossible cases.

Let's say there is a function to calculate price of item after discount :

def calculate_discount(price, discount):
    discounted_price = price - [discount*price]
    assert 0 <= discounted_price <= price
    return discounted_price

here, discounted_price can never be less than 0 and greater than actual price. So, in case the above condition is violated assert raises an Assertion Error, which helps the developer to identify that something impossible had happened.

Hope it helps :)

Nitish Chauhan
  • 375
  • 4
  • 7
3

My short explanation is:

  • assert raises AssertionError if expression is false, otherwise just continues the code, and if there's a comma whatever it is it will be AssertionError: whatever after comma, and to code is like: raise AssertionError(whatever after comma)

A related tutorial about this:

https://www.tutorialspoint.com/python/assertions_in_python.htm

U13-Forward
  • 69,221
  • 14
  • 89
  • 114
2

As written in other answers, assert statements are used to check the state of the program at a given point.

I won't repeat what was said about associated message, parentheses, or -O option and __debug__ constant. Check also the doc for first hand information. I will focus on your question: what is the use of assert? More precisely, when (and when not) should one use assert?

The assert statements are useful to debug a program, but discouraged to check user input. I use the following rule of thumb: keep assertions to detect a this should not happen situation. A user input may be incorrect, e.g. a password too short, but this is not a this should not happen case. If the diameter of a circle is not twice as large as its radius, you are in a this should not happen case.

The most interesting, in my mind, use of assert is inspired by the programming by contract as described by B. Meyer in [Object-Oriented Software Construction]( https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction%2C_2nd_Edition ) and implemented in the [Eiffel programming language]( https://en.wikipedia.org/wiki/Eiffel_(programming_language)). You can't fully emulate programming by contract using the assert statement, but it's interesting to keep the intent.

Here's an example. Imagine you have to write a head function (like the [head function in Haskell]( http://www.zvon.org/other/haskell/Outputprelude/head_f.html)). The specification you are given is: "if the list is not empty, return the first item of a list". Look at the following implementations:

>>> def head1(xs): return xs[0]

And

>>> def head2(xs):
...     if len(xs) > 0:
...         return xs[0]
...     else:
...         return None

(Yes, this can be written as return xs[0] if xs else None, but that's not the point).

If the list is not empty, both functions have the same result and this result is correct:

>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True

Hence, both implementations are (I hope) correct. They differ when you try to take the head item of an empty list:

>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range

But:

>>> head2([]) is None
True

Again, both implementations are correct, because no one should pass an empty list to these functions (we are out of the specification). That's an incorrect call, but if you do such a call, anything can happen. One function raises an exception, the other returns a special value. The most important is: we can't rely on this behavior. If xs is empty, this will work:

print(head2(xs))

But this will crash the program:

print(head1(xs))

To avoid some surprises, I would like to know when I'm passing some unexpected argument to a function. In other words: I would like to know when the observable behavior is not reliable, because it depends on the implementation, not on the specification. Of course, I can read the specification, but programmers do not always read carefully the docs.

Imagine if I had a way to insert the specification into the code to get the following effect: when I violate the specification, e.g by passing an empty list to head, I get a warning. That would be a great help to write a correct (i.e. compliant with the specification) program. And that's where assert enters on the scene:

>>> def head1(xs):
...     assert len(xs) > 0, "The list must not be empty"
...     return xs[0]

And

>>> def head2(xs):
...     assert len(xs) > 0, "The list must not be empty"
...     if len(xs) > 0:
...         return xs[0]
...     else:
...         return None

Now, we have:

>>> head1([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty

And:

>>> head2([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty

Note that head1 throws an AssertionError, not an IndexError. That's important because an AssertionError is not any runtime error: it signals a violation of the specification. I wanted a warning, but I get an error. Fortunately, I can disable the check (using the -O option), but at my own risks. I will do it a crash is really expensive, and hope for the best. Imagine my program is embedded in a spaceship that travels through a black hole. I will disable assertions and hope the program is robust enough to not crash as long as possible.

This example was only about preconditions, be you can use assert to check postconditions (the return value and/or the state) and invariants (state of a class). Note that checking postconditions and invariants with assert can be cumbersome:

  • for postconditions, you need to assign the return value to a variable, and maybe to store the iniial state of the object if you are dealing with a method;
  • for invariants, you have to check the state before and after a method call.

You won't have something as sophisticated as Eiffel, but you can however improve the overall quality of a program.


To summarize, the assert statement is a convenient way to detect a this should not happen situation. Violations of the specification (e.g. passing an empty list to head) are first class this should not happen situations. Hence, while the assert statement may be used to detect any unexpected situation, it is a privilegied way to ensure that the specification is fulfilled. Once you have inserted assert statements into the code to represent the specification, we can hope you have improved the quality of the program because incorrect arguments, incorrect return values, incorrect states of a class..., will be reported.

jferard
  • 7,835
  • 2
  • 22
  • 35
1

Assertions are statements that state a fact confidently in our program.

Syntax : assert <condition> or assert <condition>,<error message>

It has a condition/expression which is supposed to be always true. If the condition is false, the assert statement will halt the program and throw an error message saying AssertionError. So your assertion expression will be something that you don't want in your program.

e.g.

  1. assert <condition> -- using assert without <error message>

    var = int(input("Enter value 1-9 inclusive:"))                                 
    assert var!=0 
    print(var)
    

    Output :

    If input is 0 :

    AssertionError
    

    If input is 1 :

    1
    
  2. assert <condition>,<error message> -- using assert with an <error message>

    var = int(input("Enter value 1-9 inclusive:"))                                 
    assert var!=0,"Input cannot be zero"
    print(var)
    

    Output :

    If input is 0 :

    AssertionError: Input cannot be zero
    

    If input is 1 :

    1
    

Key Points :

  1. It is used as a debugging tool.
  2. It takes an expression and an optional message.
  3. It exists in almost every programming language
0

The assert keyword in Python raises an AssertionError if the code following the assert keyword is False. If not, it continues as nothing happened.

Example 1:

a = 5
b = 6

assert a == b

OUTPUT:

AssertionError

This is because, obviously, a does not equal b. This is particularly useful if you want to raise an Exception in your code.

def get_dict_key(d, k):
    try:
        assert k in d
        return d[k]
    except Exception:
        print("Key must be in dict.")

The above example is practically useless, but remember, it is mostly used for debugging purposes, so you can track down your bugs.

user
  • 1,220
  • 1
  • 12
  • 31
ujjwal_bansal
  • 317
  • 4
  • 11
-2

format : assert Expression[,arguments] When assert encounters a statement,Python evaluates the expression.If the statement is not true,an exception is raised(assertionError). If the assertion fails, Python uses ArgumentExpression as the argument for the AssertionError. AssertionError exceptions can be caught and handled like any other exception using the try-except statement, but if not handled, they will terminate the program and produce a traceback. Example:

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)    

When the above code is executed, it produces the following result:

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!    
bhavya joshi
  • 1,096
  • 10
  • 20
-4
def getUser(self, id, Email):

    user_key = id and id or Email

    assert user_key

Can be used to ensure parameters are passed in the function call.

Cleb
  • 25,102
  • 20
  • 116
  • 151
user2725012
  • 61
  • 1
  • 5
  • 2
    This will work, but from what I understand, asserts shouldn’t be used for checking user-input, because they can be turned off at run-time. If you really want to enforce or validate user-input use the `if not user_key: raise ValueError()` Check last 2 paragraphs here: https://wiki.python.org/moin/UsingAssertionsEffectively – alpha_989 Jan 14 '18 at 17:53
  • 1
    `assert` should not be used for input validation because either the validation will be stripped out if `__debug__` is `False`. Also using assertions for non-debug purposes can cause people to catch the resulting `AssertionError`s, which can make debugging more difficult instead of less. – FluxIX Aug 26 '18 at 00:33
-5
>>>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
>>>