Alexander Oh
Alexander Oh

Reputation: 25641

checking assertions in a lambda in python

I'm trying to use assertions to show some invariants (mostly in testing) Thus i want to write something like the following:

values = [ range(10) ] 
expected_values = [ range(10) ]

map (lambda x: assert x[0] == x[1] ,zip( [ run_function(i) for i in values ], expected_values))

If I use this with unittest.assertEqual this works perfectly fine , but if I want to write this with an assertion it just fails. Is there a way to fix this?

Upvotes: 15

Views: 13204

Answers (5)

lackadaisical
lackadaisical

Reputation: 1694

One simple solution is to define a auxiliary function that raises an assert given an input boolean value:

def assert_(cond): assert cond

values = [ range(10) ] 
expected_values = [ range(10) ]

map (lambda x: assert_(x[0] == x[1]) ,zip( [ run_function(i) for i in values ], expected_values))

Upvotes: 0

OverLordGoldDragon
OverLordGoldDragon

Reputation: 19806

Worked in my application, which was similar:

def _lambda_assert(fn, *args, **kwargs):
    def _assert(fn_out):
        if isinstance(fn_out, (list, tuple)):
            value, fail_msg = fn_out
            assert value, fail_msg
        else:
            assert fn_out  # value only
    return lambda: _assert(fn(*args, **kwargs))
    # return lambda x: _assert(fn(*args, **kwargs))  # for pytest; need dummy positional

Usage example:

import numpy as np

def _test_precision(size, atol=1e-2):
    x = np.random.randn(size)
    y = np.random.randn(size)
    absdiff = np.abs(x - y)
    fail_msg = f"absdiff: {absdiff}; atol={atol}"
    return np.allclose(x, y, atol=atol), fail_msg

lambda_assert = _lambda_assert(_test_precision, 20, atol=1)

Upvotes: 1

Tal Weiss
Tal Weiss

Reputation: 8999

Actually you can:

assertion_raiser = lambda: (_ for _ in ()).throw(AssertionError("My Lambda CAN raise an assertion!"))

Here is some validation:

try:
    assertion_raiser()
except AssertionError:
    print("assertion caught")

Upvotes: 7

Noufal Ibrahim
Noufal Ibrahim

Reputation: 72795

Unfortunately, assert is a statement and Pythons limited lambdas don't allow that in them. They also restrict things like print.

You can use a generator expression here though.

assert all(x[0] == x[1] for x in  zip( [run_function(i) for i in values ], expected_values))

I personally think that the following would be more readable

assert all(run_function(i) == j for i,j in zip(inputs, expected_values))

Upvotes: 12

Felix Kling
Felix Kling

Reputation: 816780

From the documentation:

Note that functions created with lambda forms cannot contain statements.

assert is a statement.

So no, you cannot use the assert statement in a lambda expression.

Upvotes: 13

Related Questions