Is it possible to evaluate a function return is in a list else return a default value?

Viewed 98

If I have a function that returns some value and I only want to assign that value if its in an allowed list otherwise use a default. Assume I can't modify the function.

ie this works, but its calling the function twice.

def some_func():
    return 'foo'

allowed_list = ['foo', 'bar']
value = some_func() if some_func() in allowed_list else 'default'

is there a pythonic way to set the value in a single line without calling the function twice?

3 Answers

From Python 3.8:

value = x if (x:=foo()) in allowed_list else 'default'

If you enjoy doing some overkill to do simple tasks(assignment expressions/walrus operator), define a decorator which takes care of the returned value for you :

allowed_list = ['foo', ]

def check_return_value(fn):
    def inner(*args, **kwargs):
        result = fn(*args, **kwargs)
        return result if result in allowed_list else 'default'

    return inner


# suppose this name is imported from somewhere else and you can't use @ syntax
def some_func():
    return 'boo'

some_func = check_return_value(some_func)

var = some_func()
print(var)  # prints "default"

As long as you're confined to Python 3.6 and can't use assignment expressions, you could make yourself a helper function to handle this.

def some_func():
    return 'foo'

def default_if_invalid(value, allowed_values, default):
    return value if value in allowed_values else default

allowed_list = ['foo', 'bar']
value = default_if_invalid(some_func(), allowed_list, 'default')

This can be easily modified if, say, you always check against the same list of allowed values, or if you want the method to supply a default default (perhaps None) if one isn't provided. For instance:

def default_if_invalid(value, default=None):
    allowed_list = ['foo', 'bar']
    return value if value in allowed_values else default

value = default_if_invalid(some_func()) # sets to None if not in list
value = default_if_invalid(some_func(), 'default') # specifies a default
Related