user3375672
user3375672

Reputation: 3768

python use result of function to decide if function result should be used

Often you want to use None as a return value for functions. Is there a Python idiom to avoid calling a function two times if you want either do one thing if the function returns None and if not use the result of the function. Below is a silly example.

def foo(a, b):
  if b == 0:
    return(None)
  else:
    return(a/b)


a = b = 2
if foo(a, b) is None: #Do one thing. 1st call to function.
  print('b cannot be null')
else: #Use the result of function. 2nd function call.
  print('The result is: ' + str(foo(a,b)) )

Is this stateful way the alternative (with only one function call, but need to assign result, which could be huge, to a variable) ?:

res = foo(a, b)
if res is not None: 
  print('The result is: ' + str(res) )
else:
  print('b cannot be null')

Upvotes: 3

Views: 601

Answers (1)

Thierry Lathuille
Thierry Lathuille

Reputation: 24232

In your example, foo returns None to mean: "Something in the parameters is wrong, and I can't return a valid value". In that case, it would be clearer to use an exception:

def foo(a, b):
    if b == 0:
        raise ValueError("b can't be zero")
    else:
        return a/b

So, if b is null, foo won't return anything - and you won't have to test the return value to check if it's valid, or if it means "something wrong happened". If foo returns something, you're certain that it is a valid result.

Now, to use foo, you would use a try ... except block:

a = 2
b = 0

try:
    print('The result is: ' + str(foo(a,b)) )
except ValueError as msg:
    print(msg)

# b can't be zero

If you don't put the call to foo in such a block, your program will stop with a nice, informative error message:

foo(a, b)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-36-89e9686ab4be> in <module>()
     14     print(msg)
     15 
---> 16 foo(a, b)

<ipython-input-36-89e9686ab4be> in foo(a, b)
      1 def foo(a, b):
      2     if b == 0:
----> 3         raise ValueError("b can't be zero")
      4     else:
      5         return a/b

ValueError: b can't be zero

which is also good, because your program should fail immediately when something goes wrong.

Upvotes: 2

Related Questions