# Python3: Functions

July 26, 2018

In the tutorials so far in this course, you’ve used functions many times. In this tutorial, you’ll see how to create new ones!

Remember functions like len() that you can execute in Python? Well, good news – you will learn how to write your own functions now!

A function is a sequence of instructions that Python should execute. Each function in Python starts with the keyword def, is given a name, and can have some optional parameters. Let’s give it a go. Take the look at the following code.:

def hi():
print('Hi there!')
print('How are you?')
hi()

Okay, our first function is ready!

You may wonder why we’ve written the name of the function at the bottom of the program. The first time (line 1), we’re defining what the function does. The second time (line 5), we’re calling the function, i.e. asking Python to actually execute the function.

Note that Python reads the file and executes it from top to bottom. As Python is executing the program, if it hasn’t yet found the function definition, it will throw an error. Hence, we define the function before calling it.

Go ahead and run the above and see what happens.

Output:

Hi there!
How are you?

Note: if it didn’t work, don’t panic! The output will help you to figure why:

• If you get a NameError, that probably means you typed something wrong, so you should check that you used the same name when creating the function with def hi(): and when calling it with hi().
• If you get an IndentationError, check that both of the print lines have the same whitespace at the start of a line: python wants all the code inside the function to be neatly aligned.
• If there’s no output at all, check that the last hi() isn’t indented - if it is, that line will become part of the function too, and it will never get run.

Let’s build our first function with parameters. We will use the previous example. but this time, we’ll write a function that says ‘hi’ to the person’s name passed in as a parameter:

def hi(name):

As you can see, we now gave our function a parameter that we called name:

def hi(name):
if name == 'CommonLounge':
print('Hi CommonLounge!')
elif name == 'Dave':
print('Hi Dave!')
else:
print('Hi anonymous!')
hi()

Within the function, a parameter works exactly the same as a variable.

Also remember: The print function is indented four spaces within the if statement. This is because the function runs when the condition is met. Let’s see how it works now:

Traceback (most recent call last):
File "python_intro.py", line 10, in
hi()
TypeError: hi() missing 1 required positional argument: 'name'

Oops, an error. Luckily, Python gives us a pretty useful error message. It tells us that the function hi()(the one we defined) has one required argument (called name) and that we forgot to pass it when calling the function.

We’re using the words parameters and arguments interchangeably. We think parameters is much more clear to a beginner, but arguments is the word used conventionally.

Let’s fix it at the bottom of the file:

hi("CommonLounge")

And run it again:

Hi CommonLounge!

And if we change the name?

hi("Dave")

And run it:

Hi Dave!

Now, what do you think will happen if you write another name in there? (Not CommonLounge or Dave.) Give it a try and see if you’re right. It should print out this:

Hi anonymous!

This is awesome, right? This way you don’t have to repeat yourself every time you want to change the name of the person the function is supposed to greet. And that’s exactly why we need functions – you never want to repeat your code!

Let’s do something smarter – there are more names than two, and writing a condition for each would be hard, right? Let’s fix that.

def hi(name):
print('Hi ' + name + '!')
hi("Rachel")

Let’s run the code now:

Hi Rachel!

# Multiple parameters and return values

So far, you have seen functions which take one parameter, and print something based on that. In fact, a function can take multiple inputs, and also return a value. Here’s a simple example,

def subtract(x, y):
return x - y
z = subtract(5, 2)
print(z) # Outputs: 3

The above subtract function takes two inputs, which it calls x and y. It then returns the result of subtracting y from x. Hence, when we call subtract(5, 2), the returned value is 3. You can assign this value to a variable, or use it any other way you want.

Also, recall that you have already used functions before which return a value (len and input). Now you can write your own!

When evaluating an expression, functions evaluate to the value they return. For example:

subtract(5, 2) + 8
=> 3 + 8
=> 11 

Note that you can also return a string, list, dictionary, etc. Here’s an example of a function which returns a dictionary.

def math(x, y):
return { 'sum': x+y, 'difference': x-y, 'product': x*y, 'quotient': x/y }
print(math(5, 2))
# Outputs: {'sum': 7, 'difference': 3, 'product': 10, 'quotient': 2.5}

# None data type

If you don’t return anything from a function it returns None by default. None is a data type in Python, just like int or bool (you’ve now seen all the data types, recapped at the bottom of this article). None is a special value, and None is the only value of type None. It’s often used to denote special cases such as missing values. For example:

def minimum(array):
# return None if array is empty
if len(array) == 0: return None
# ... rest of the code goes here ...
# ... calculate the minimum and return ...
print(minimum([]))      # None

Note: In the console, if the result is None, and you do not use print(), then the console does not show any result.

# Keyword arguments and Optional arguments

There’s one last thing about functions you should know — keyword and optional arguments.

Take a look at the function below:

def hi(name="CommonLounge"):
print("Hi " + name + "!")
hi()                 # "Hi CommonLounge!"
hi(name="Alice")     # "Hi Alice!"
hi("Alice")          # "Hi Alice!"

In the above, def hi(name="CommonLounge") means that if the arguments name is not given when calling the function (line 4), the default value of name will be "CommonLounge". If the argument is in the correct position, you can pass the argument with (line 5) or without (line 6) the keyword.

Keyword arguments come in especially handy when functions have a lot of arguments. Let’s see an example:

def greet(name="CommonLounge", greeting="Hi"):
print(greeting + " " + name + "!")
## Here are *ALL* the ways you can call the function.
# No arguments
greet()                                 # "Hi CommonLounge!"
# Arguments by position
greet("Alice")                          # "Hi Alice!"
greet("Alice", "Hello")                 # "Hello Alice!"
# Arguments by keyword
greet(name="Alice")                     # "Hi Alice!"
greet(greeting="Hello")                 # "Hello CommonLounge!"  (*important)
greet(name="Alice", greeting="Hello")   # "Hello Alice!"
greet(greeting="Hello", name="Alice")   # "Hello Alice!"         (*important)
# Mixed
greet("Alice", greeting="Hello")        # "Hello Alice!"
# greet(name="Alice", "Hello")          # ERROR! When mixing position and
# keyword arguments, keyword arguments
# must go at the end 

In particular, notice that when passing arguments by keyword, we have the option of not passing the first argument but still passing the second argument (line 14), or passing the arguments out of order (line 16).

Finally, you can also write functions where some arguments are mandatory and some optional. For example:

def greet(name, greeting="Hi"):
print(greeting + " " + name + "!")
# You can call it in the following ways
greet("Alice")                          # "Hi Alice!"
greet("Alice", "Hello")                 # "Hello Alice!"
greet("Alice", greeting="Hello")        # "Hello Alice!"

In the above function, name is a mandatory argument, and greeting is optional. In all cases, the first argument must be passed — if it is not passed, then an error will be thrown. Only the second argument can be passed as a keyword argument.

Congratulations! You just learned how to write functions! :)

# Examples: element_counter and reverse_list

Next, let’s have some fun writing our own functions from scratch.

Suppose we want to write a function that counts the number of times an element appears in a list. This function accepts two arguments — the list, and the element. Let’s call our function element_counter. This is one way to go about implementing it:

def element_counter(lst, element):
occurrences = 0
for item in lst:
if item == element:
occurrences += 1
return occurrences
print(element_counter([1,2,3,3], 3))  ## Output: 2

Awesome! Besides doing what it’s meant to do, we can use the same function to do a couple more things:

1. If we want to check if an element exists in a list, we can check element_counter(lst, item) > 0
2. If we want to check if an element exists more than once in an array (i.e. has a duplicate), we can check element_counter(lst, item) > 1

Next, let’s write a function to reverse a list. We already saw earlier that we can do this by calling .reverse() method. Suppose we want to write a similar function from scratch, which makes sure that it returns the reversed list:

def reverse_list(lst):
new_list = []
for item in lst:
new_list = [item] + new_list
return new_list
lst = ['a', 'b', 'c', 'd']
print(reverse_list(lst))  ## Output: ['d', 'c', 'b', 'a']

The real magic happens on line 4: we use list concatenation using the + operator to add subsequent new elements at the start of the new_list that is initialized as empty list on line 2.

# Summary

Let’s recap what we just learned:

• Writing our own functions using def()
• Multiple parameters and return values
• None data type
• Keyword arguments and Optional arguments
• Examples: element_counter and reverse_list

That’s it. You totally rock! This was a tricky chapter, so you should feel proud of yourself. We’re definitely proud of you for making it this far!

# Appendix: List of all Primitive Data Types

The following is a list of primitive data types in Python. By primitive, we mean we are only including data types which can’t be broken down further. (we’re excluding non-primitive datatypes such as lists and dictionaries).

Data type | Examples                          | Description
==========|===================================|========================================
int      | 5, -1, 0, 127                     | integer
float    | 5.3, -1.7, 2.0, 2.33333333        | floating-point values (decimal values)
str      | 'a', 'Commonlounge', '12', 'v1.0' | string
bool     | True, False                       | boolean
NoneType | None                              | used to denote special / missing values

Based on content from https://tutorial.djangogirls.org/en/python_introduction/