π Return Output using Functions
Contents
π Return Output using Functions#
The value in functions come from their ability to perform operations on an input and return a new output.
Explicit Return statement#
Aside: Why the number 42?
The number 42 is especially significant to fans of science fiction novelist Douglas Adamsβ βThe Hitchhikerβs Guide to the Galaxy,β because that number is the answer given by a supercomputer to βthe Ultimate Question of Life, the Universe, and Everything.β
def return_42():
return 42 # An explicit return statement
return_42()
42
You can modify an explicit return statement
return_42() * 2
84
return_42() - 2
40
Functions with Inputs and returns#
def mean(sample):
return sum(sample) / len(sample)
mean([1, 2, 3, 4])
2.5
Implicit Return Statements#
def add_one(x):
results = x + 1
value = add_one(5)
value
print(value)
None
Why did this return None?
No return statement was provided thus an implicit return of None
was inferred.
Returning multiple values#
You can have a Python function return multiple values
import numpy as np
def statistics(sample):
mean = np.mean(sample)
median = np.median(sample)
# find unique values in array along with their counts
vals, counts = np.unique(sample, return_counts=True)
# find mode
mode = np.argwhere(counts == np.max(counts))
return mean, median, mode
mean, median, mode = statistics([0, 1, 2, 3, 3, 4, 5])
print(mean)
print(median)
print(mode)
2.5714285714285716
3.0
[[3]]
Functions calling Functions#
def adder(number, value):
return number + value
def multiplier(number, factor):
return number * factor
multiplier(adder(10, 1), 10)
110
Functions by Closure#
Because functions are object you can return a function that is modified by some input
def by_factor(factor):
def multiply(number):
return factor * number
return multiply
Letβs break this down:
You start by calling by_factor with an input of factor.
factor is locally defined so when you run multiply it uses the value for factor
return multiply returns the function with the factor implemented
This function can be used by inputting a number
double = by_factor(2)
double(3)
6
double(12)
24
triple = by_factor(3)
triple(3)
9
triple(12)
36
Advanced Topic (not on exam - maybe bonus): Decorators#
Decorators are tools that take one function as an input and extend its capabilities.
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
def say_whee():
print("Whee!")
say_whee = my_decorator(say_whee)
say_whee()
Something is happening before the function is called.
Whee!
Something is happening after the function is called.
Beautiful Python#
Python has a lot of ways to simplify syntax. This might be confusing at first but makes for really nice and simple code
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_whee():
print("Whee!")
say_whee()
Something is happening before the function is called.
Whee!
Something is happening after the function is called.
Creating decorator files#
You can create Python files, import them, and use them as decorators
%%writefile decorators.py
def do_twice(func):
def wrapper_do_twice():
func()
func()
return wrapper_do_twice
Overwriting decorators.py
from decorators import do_twice
@do_twice
def say_whee():
print("Whee!")
say_whee()
Whee!
Whee!
Decorators with Arguments#
from decorators import do_twice
@do_twice
def greet(name):
print(f"Hello {name}, I am a Drexel Dragon")
greet("Jay")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
c:\Users\Joshua Agar\Documents\codes\Winter_2023_ENGR_131_private\jupyterbook\week4\lecture4\Functions_that_Return.ipynb Cell 47 in <cell line: 1>()
----> <a href='vscode-notebook-cell:/c%3A/Users/Joshua%20Agar/Documents/codes/Winter_2023_ENGR_131_private/jupyterbook/week4/lecture4/Functions_that_Return.ipynb#Y110sZmlsZQ%3D%3D?line=0'>1</a> greet('Jay')
TypeError: wrapper_do_twice() takes 0 positional arguments but 1 was given
The problem is that the inner function wrapper_do_twice() does not take any arguments, but name=βWorldβ was passed to it.
The solution is to use *args and **kwargs in the inner wrapper function. Then it will accept an arbitrary number of positional and keyword arguments.
def do_twice(func):
def wrapper_do_twice(*args, **kwargs):
func(*args, **kwargs)
func(*args, **kwargs)
return wrapper_do_twice
@do_twice
def greet(name):
print(f"Hello {name}, I am a Drexel Dragon")
greet("Jay")
Hello Jay, I am a Drexel Dragon
Hello Jay, I am a Drexel Dragon