Reputation: 5741
I have a couple of functions that return either a number or None
. I want my wrapper function to return the first result that is not None
. Is there any other way to do this than as following?
def func1():
return None
def func2():
return 3
def func3():
return None
def wrapper():
result = func1()
if result is not None:
return result
result = func2()
if result is not None:
return result
result = func3()
if result is not None:
return result
I am aware of return func1() or alternative
; which returns the outcome of func1()
unless it is None
, then alternative
is returned. In the most optimal situation I do something like (pseudo code):
return func1() or continue
return func2() or continue
return func3() or continue
Upvotes: 2
Views: 192
Reputation: 530922
You need a loop which will return the first non-None
value it finds.
def wrapper():
for f in [func1, func2, func3]:
result = f()
if result is not None:
return result
If every function returns None
, wrapper
will as well by reaching the end of the body without an explicit return
.
Shortened slightly in Python 3.8 or later,
def wrapper():
for f in [func1, func2, func3]:
if (result := f()) is not None:
return result
You can also make use of the any
function:
def wrapper():
if any((result := f()) is not None for f in [func1, func2, func3]):
return result
(I prefer the explicit loop; YMMV.)
Upvotes: 4
Reputation: 42143
You could combine map, filter and next:
def func1():
print("executed func1()")
return None
def func2():
print("executed func2()")
return 3
def func3():
print("executed func3()")
return None
functions = (func1,func2,func3)
call = lambda f:f()
result = next(filter(None,map(call,functions)),None)
print("result:",result)
output:
executed func1()
executed func2()
result 3
func 3 is not executed
If your functions have parameters you can still use this approach by building the list of functions with lambdas:
def func1(p1):
print(f"executed func1({p1})")
return None
def func2(p2a,p2b):
print(f"executed func2{(p2a,p2b)}")
return 3
def func3(p3):
print(f"executed func3({p3})")
return None
functions = [
lambda: func1(10),
lambda: func2("X",99),
lambda: func3(3.5)
]
call = lambda f:f()
result = next(filter(None,map(call,functions)),None)
print(result)
output:
executed func1(10)
executed func2('X', 99)
3
Upvotes: 1
Reputation: 59096
If there's only three functions, and you don't care about distinguishing None from other falsey values, you can use
return func1() or func2() or func3()
If there are lots of functions, or if you want to be more discriminating about the return values, then you could put them all in a list and use
return next(x for x in (f() for f in funcs) if x is not None)
If you want to cope with all of your functions returning None, you can add a default value for next, e.g.
return next((x for x in (f() for f in funcs) if x is not None), None)
Upvotes: 2
Reputation: 15364
You can do this:
def wrapper():
functions = [func1, func2, func3]
return next(filter(lambda result: result is not None,
f() for f in functions),
None)
It returns None
if all the functions return None
.
Upvotes: 0