If we want to do the same thing in multiple places in our code then we can use functions rather than copy pasting.
This also allows us to abstract away complexity, as we can make a function perform some complicated operations, and then forget about how it actually works.
We create functions using the def keyword - This process is called "definition"
# "Declare" a function
print("I'm nOT DysFUnctIonaL!")
# "Call" the function twice
# This will print the sentence twice
Most of the time, we use functions to carry out an operation and collect the result. return allows us to get the function to give us an output.
# Return lower-case user input from the function
user_input =input("All good in the hood? ")
user_input = user_input.lower()# Convert to lowercase
return user_input # <---
Then we can use the function, storing the output in a variable
lowered_input = get_lowercase_input()
If we want our function to manipulate some data, we can add "parameters" into the definition of the function. Then any time we try and call it, we will need to provide something - doing so is referred to as passing arguments.
We've already seen examples of this:
# Some in-built python functions
input("We can pass a string to the input function")
In order to add this functionality to our functions, we include the parameters in the definition of the function - specifically, inside the brackets next to the function's name:
# Function prints the first and last character in string
# Prints ae
If the function takes arguments, then we have to provide them. (unless we use default arguments - see extensions)
It's also important to remember that the type of variable you pass to the function matches what the person who defined it (probably you) expected:
# But, we HAVE to pass something compatible!
first_and_last()# ERROR - Need to pass something!
first_and_last(1321)# ERROR - We can't use variable[index] on integers
It can be a good idea to add type checking to your functions to make sure that the arguments a user passes in are compatible with the operations that your function performs:
# Need to think about these things!
defo_string =str(mebbe_string)# Throws error if not a valid type cast
Modules and Packages
We don't want to reinvent the wheel - If someone has implemented something for us, then we can just use that. But first, some definitions:
Module - a file containing functions. The filename is module_name.py
Package - a collection of modules
Library - a collection of packages (doesn’t necessarily provide just one functionality)
If we want to use modules/packages in our scripts, then once we've installed them (either using anaconda's navigator software, or PIP) we need to import them. This is done by using the import statement, e.g.:
# "time" is a package which comes with python
import time # We import the time module
time.sleep(3)# sleep function is part of time module
Sometimes we don't want to import everything from a package - we can pick specific modules using from
E.g. if we have our own function, also called sleep(), we probably don't want to import the sleep() function from time
Additionally, if we use from, we don't need to explicitly call the function via the module
# All I want to do is sleep
from time import sleep
sleep(3)# Don't need to call via time module
If we want to refer to the imported functions or modules using a different name, then we can import them as something else
from time import sleep as meditate
This can be useful if you have a function with the same name, or if the name of the module/function is annoyingly long