3. Point of No Return

What a function returns and what it does not can cause a lot of confusion, especially if the function causes some side effects in addition to returning a value. Here's the difference:

  • Functions return some object, like a number, a string, an element of a class, or even another function. If the body of a function doesn't contain a return statement, Python assumes that the function returns a None.
  • Functions might make some side effects, meaning it change some state (usually a variable) that was originally defined outside its scope.

A common side effect is printing some value within your function. Side effects have the potential to cause confusion. You might often see that the result of your function being printed out, but the return value of your function call doesn't seem to contain the result you just calculated.

Consider the following case as an example. What do you expect the result of the second print statement to be ?


In [ ]:
def function_of_no_return(a):
    print ("Parameter passed to the function is {0}".format(a))
    
x = function_of_no_return(42)
print ('Function returns', x)

If a function returns nothing, nothing (or None in Python) is going to be printed.

But what if our function returns a print statement?


In [ ]:
def function_of_print_return(a):
    return print ("Parameter passed to the function is {0}".format(a))
    
x = function_of_print_return(42)
print ('Function returns', x)

You might say "Waaaaait a second, there is a return here in my function!". Well, that's kinda true. Here return returns whatever the print function returns. Since the print function returns None, and as a side effect of its work it prints whatever you've asked, you should expect a None result. In other words, although print function prints out some text in human readable form on your Input/Output device (Out cell), it does not return any useful Python object.

If you want to print and return something, you need to call the print function from your function as well as return a value that you need using the return statement.


In [ ]:
def proper_function(a):
    print ("Parameter passed to the function is {0}".format(a))
    return a
    
x = proper_function(42)
print ('Function returns', x)

Now let's do something useful. Here's a function that should return an integer part of half of a number. So, half(5) == 2, as well as half(4) == 2. The problem is, the function is faulty and it doesn't do what it should (clearly, someone with knowledge of Python 2, not Python 3 wrote it). Add some print statements to debug and modify the function so it passes testcases.


In [ ]:
def half(num):
    h = num/2
    return h

h_true = 2

h = half(4)
print("half(4) -> {} [True: {}]".format(h, h_true))
assert h == h_true
assert type(h) == int

h = half(5)
print("half(5) -> {} [True: {}]".format(h, h_true))
assert h == h_true
assert type(h) == int

print("\n(Passed!)")