I have a chain of functions, all defined elsewhere in the class:
fus(roh(dah(inp)))
where inp
is either a dictionary, or bool(False)
.
The desired result is that if inp
, or any of the functions evaluate to False
, False
is returned by the function stack.
I attempted to use ternary operators, but they don't evaluate correctly.
def func(inp):
return int(inp['value']) + 1 if inp else False
throws a TypeError, bool not subscriptable, if i == False
because inp['value']
is evaluated before the conditional.
I know I can do it explicitly:
def func(inp):
if inp == False:
return False
else:
return inp['value'] + 1
but there are a ton of functions, and this will nearly quadruple the length of my code. It's also rewriting the exact same lines of code again and again, which suggests to me that it is the wrong way to do things.
I suspect that a decorator with arguments is the answer, but the more I play around with it the less sure I am about that.
def validate_inp(inp):
def decorator(func):
def wrapper(*args):
return func(inp) if inp else False
return wrapper
return decorator
@validate_inp(inp)
def func(inp):
return int(inp['value']) + 1
Unfortunately the decorator call throws a NameError, 'inp' not defined. But I'm not sure if I'm using the decorator incorrectly, or the decorator is the wrong solution.
Looking for comment, criticism, suggestion, and/or sanity check.
You probably want to be using empty dictionaries instead of boolean False. Props to @chepner.
In my application, using False was "okay" but offered no advantages and caused some chunky blocks of code.
I've found everything is simpler using an empty dictionary instead. I'm wrapping the functions that use the dict with a decorator that catches the KeyError thrown by referencing dict['value']
where dict
is empty.
You can check if a value is either truthy or falsy with the built-in bool() function. According to the Python Documentation, this function: Returns a Boolean value, i.e. one of True or False .
We can evaluate values and variables using the Python bool() function. This method is used to return or convert a value to a Boolean value i.e., True or False, using the standard truth testing procedure.
Decorator should look like:
def validate_inp(fun):
def wrapper(inp):
return fun(inp) if inp else False
return wrapper
@validate_inp
def func(inp):
return int(inp['value']) + 1
print(func(False))
print(func({'value': 1}))
If you want to use your decorator with a class member:
def validate_inp(fun):
def wrapper(self, inp):
return fun(self, inp) if inp else False
return wrapper
class Foo(object):
@validate_inp
def func(self, inp):
return int(inp['value']) + 1 if inp else False
foo = Foo()
print(foo.func(False))
print(foo.func({'value': 1}))
I attempted to use ternary operators, but they don't evaluate correctly.
def func(inp): return int(inp['value']) + 1 if inp else False
throws a TypeError, bool not subscriptable, if
i == False
becauseinp['value']
is evaluated before the conditional.
This is not true - that code works. Further, you can just write
def func(inp):
return inp and (int(inp['value']) + 1)
To automatically wrap functions like this, make a function that wraps a function:
def fallthrough_on_false(function):
def inner(inp):
return inp and function(inp)
return inner
This should be improved by using functools.wraps
to carry through decorators and names, and it should probably take a variadic number of arguments to allow for optional extensions:
from functools import wraps
def fallthrough_on_false(function):
@wraps(function)
def inner(inp, *args, **kwargs):
return inp and function(inp, *args, **kwargs)
return inner
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With