2

For example, what assert does:

assert <boolean assertion to check>, <error string/value outputted if that assertion False>

What I would like to do:

mycommand <boolean assertion to check>, <value that will get returned if assertion is False>

It would be the same as doing:

if not <boolean assertion to check>: return <value>

but concisely, with a simple one-liner. I know I should just use this last one, but I am more interested on finding out how much you can override/customize python.

quan2m
  • 43
  • 1
  • 7
  • 1
    You can't. The closest you can get is a function (although obviously you can't handling returning from a separate function). You could write your own preprocessor or try finding an existing one, but there's no built-in way. – Carcigenicate Nov 20 '19 at 15:15
  • Might be worth reading through this question: https://stackoverflow.com/questions/15669921/adding-macros-to-python – Donut Nov 20 '19 at 15:19
  • 1
    If you write code that needs so many of these kinds of statements that you're thinking about customising Python like this, then I'd suggest you should rather write the code differently, as that sounds like a red flag. – deceze Nov 20 '19 at 15:23
  • Or write in a lisp where this kind of thinking is common and even encouraged (I recommend Clojure). – Carcigenicate Nov 20 '19 at 15:23
  • @deceze I knew I was going to get this answer and you are probably right lol.. anyway, what if I have to perform multiple checks on a Flask GET instance for some json content? [current snippet] (https://i.imgur.com/u8FbMSu.png) – quan2m Nov 21 '19 at 12:31
  • I'd probably dress that up as many individual validation functions/classes which each raise their own sort of `ValidationException` and chain them. More a declarative approach than a procedural one. E.g., libraries like WTForms and such implement this kind of approach. – deceze Nov 21 '19 at 12:33

2 Answers2

2

If what you are looking for a one-expression if statement (rather than an assertion that causes failure if false), then do this:

<value> if <boolean assertion to check> else <another value>

If you don't have anything for <another value>, it is Pythonic to let that be None.

x = 3 if 10<5 else None gives x the value None.

x = 3 if 10>5 else None gives x the value 3.

Joshua Fox
  • 18,704
  • 23
  • 87
  • 147
2

You can not use any "user-defined" syntax, but you could just use assert itself and use a decorator to make the function return the value instead of raising an AssertionError:

def assert_to_return(f):
    def _f(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except AssertionError as e:
            return e.args[0] if e.args else None
    return _f

@assert_to_return
def div(x, y):
    assert y != 0, float("nan")
    return x / y

print(div(42, 5)) # 8.4
print(div(42, 0)) # nan

This way, the assert <condition>, <value> line means "check whether <condition> holds, otherwise immediately return <value>", i.e. pretty much exactly what you wanted. If the <value> is omitted, the function will just return None in that case, as defined in the decorator. Also note that <value> is only evaluated if the assert is violated, i.e. it could also contain an expensive function call or side-effects that you do not want to occur otherwise.

Of course, while other exceptions will work just fine, any AssertionError raised by assert statements in functions your function is calling will also bei caught and handled by the decorator. If this is a problem, you could either (a) wrap the <value> in some special wrapper object and only return those in _f, otherwise re-raise the AssertionError, or (b) wrap all the functions you call in your function that might also raise an AssertionError so that their AssertionErrors are wrapped in another exception.

tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • Thanks for the answer! I think this is the closest to what I was looking for. It's interesting to see a solution that involves decorators, I didn't know much about them. – quan2m Nov 21 '19 at 12:34