---
# System prepended metadata

title: 'Lesson 6: Functions'
tags: [Python Workshop 沈煒翔]

---

---
tags: Python Workshop 沈煒翔
---

# Lesson 6: Functions

## Functions

Functions is a block of code which only runs when it is called. We can pass data (called arguments/parameters) into a function and the function can return some data as results.

![](https://i.imgur.com/UfuZt8F.png)

In Python, we can contruct a function using the ```def``` and ```return``` keywords.

```python
# This is a function
def double(n):
    x = 2*n
    
    return x

y = double(4) # calling a function
print(y)
# >>> 8
```

Since Python code is executed sequentially, functions have to be first defined before calling them.

```python
# This would not work!
y = double(4) # >>> name 'Double' is not defined
print(y)

def double(n):
    x = 2*n
    
    return x
```

In Python, arguments and the return results could be arbitrary data type.

```python
def get_biggest(input_list):
    biggest = input_list[0]
    
    for num in input_list:
        if num > biggest:
            biggest = num
    
    return biggest

l = [1, -6, 7, 8]
b = get_biggest(l)

print(b) # >>> 8
```

### Practice

Write a function that takes a list as argument and makes all negative elements positive.

```python
l = [-1, -7, 8]

# >>> [1, 7, 8]
```

```python
def make_positive(input_list):
    output_list = []
    for num in input_list:
        if num < 0:
            output_list.append(num*-1)
        else:
            output_list.append(num)
            
    return output_list

def make_positive(input_list):
    for i, num in enumerate(input_list):
        if num < 0:
            input_list[i] = num * -1
        else:
            input_list[i] = num
    
    return input_list
```

Write a function that takes a dictionary as argument and returns a dictionary whose keys are all lower cases. Then, use the function to modify the input dictionary.

```python
d = {'Apple': 30, 'orange': 20, 'Grapes': 50}	

# 'Apple'.lower() -> 'apple'

# >>> {'apple': 30, 'orange': 20, 'grapes': 50}
```

```python
def make_key_lower(input_d):
    output_d = {}
    
    for key in input_d.keys():
        output_d[key.lower()] = input_d[key]
    
    return output_d

d2 = make_key_lower(d)
print(d2)
```

## Function arguments and returns

Functions can have no argument at all.

```python
def get_prime_number_list():
    return [2, 3, 5, 7, 11, 13, 17, 19]
```

Functions can have multiple arguments or multiple return values

```python
def print_info(name, age, gender):
	print(f'{name} is a {age}-year-old {gender}.')
	
	# if nothing needs to be returned, we don't need to write return

print_info('Tom', 20, 'boy')
print_info('Amy', 20) # >>> TypeError: print_info() missing 1 required positional argument: 'gender'
```

```python
def get_list_head_tail(l):
	return l[0], l[-1] # use "," to separate the return values

l = [1, 2, 3, 4, 5]
head, tail = get_list_head_tail(l) # Also use "," to collect multiples return values from functions

print(head) # >>> 1
print(tail) # >>> 5
```

### Practice

Write a function that takes two lists as input and returns the maximum and minimum values of the two lists.

```python
list1 = [1, -6, 7, 8]
list2 = [2, 3, 5, 7]

# >>> 8 -6
```

```python
def get_biggest_smallest(l1, l2):
    l3 = l1 + l2
    
    biggest = l3[0]
    smallest = l3[0]
    
    for num in l3:
        if num > biggest:
            biggest = num
        if num < smallest:
            smallest = num
    
    return biggest, smallest

a, b = get_biggest_smallest(list1, list2)
```

### default arguments

```python
def print_info(name, age, gender='girl'):
	#
	print(f'{name} is a {age}-year-old {gender}.')
	
	# if nothing needs to be returned, we don't need to write return

print_info('Tom', 20, 'boy')
print_info('Amy', 20)
```

## Scope

A variable is only available from inside the region it is created. This is called scope.

### Local Scope

A variable created inside a function belongs to the local scope of that function, and can only be used inside that function.

```python
def func():
    x = 300
    print(x)

func() # >>> 300
print(x) # >>> NameError: name 'x' is not defined
# because the scope of x is only inside the function
```

### Global Scope

A variable created in the main body of the Python code is a global variable and belongs to the global scope.

Global variables are available from within any scope, global and local.

```python
x = 300

def myfunc():
    print(x) # x is access from the global scope

myfunc() # >>> 300
print(x) # >>> 300
```

Most of the time, programmers avoid using any global scope variables because they may be defined anywhere and may accidentally be replaced.

-> Functional programming, object-oriented programming

```python
PI = 3.14 # global scope variables 
# we often use all capital letters for fixed value variables

def circle_area(radius):
    return 0.5 * PI * radius**2
```

### Practice

Write two functions. They both take a list as input and they perform:
1. Normalize the list
2. Calculate the inner product (element-wise multiplication) of two lists

```python
l1 = [-9, 3, 17, 0, 5]
l2 = [5, 1 0, 3, -4]

def normalize_list(input_list):
    # something here

def get_inner_product(list1, list2):
    # something here

# >>> [0, 3, 0, 5]
```

## Import functions from other files

The biggest advantages of using functions is that we can separate a huge task into multiple different small problems. It is easier to write and read code when every function only perform some small simple tasks.

We can write functions in other files and import them into our current code.

```python
# f.py
# This file only contains functions

def double(n):
    x = 2*n
    
    return x

def print_info(name, age, gender):
	print(f'{name} is a {age}-year-old {gender}.')
    
def get_prime_number_list():
    return [2, 3, 5, 7, 11, 13, 17, 19]    
```

```python
# main.py
# This file is the main code you would execute

# We can import the functions from other files when they are placed in the same folder
from f import double

x = 2
print(double(x)) # >>> 4

l = get_prime_list() # >>> NameError: name 'get_prime_list' is not defined
```

## Class practice

Given a list of tuples, write the following functions:

1. Get list of certain education level
```python
def filter_education_level(datas, level):
	# some code here

d = filter_education_level(datas, 'PhD')
print(d) # >>> [('PhD', 1208), ('PhD', 1207)]
```

2. Get average salary of the list
```python
def get_average(datas)
```

Then, use the two functions to get the average salary of master and PhD. 

```python
datas = [('master', 1038),
 ('bachelor', 843),
 ('master', 1034),
 ('master', 1008),
 ('bachelor', 810),
 ('master', 1004),
 ('bachelor', 839),
 ('bachelor', 806),
 ('master', 990),
 ('master', 999),
 ('bachelor', 750),
 ('bachelor', 758),
 ('bachelor', 764),
 ('bachelor', 790),
 ('bachelor', 792),
 ('master', 1030),
 ('PhD', 1208),
 ('master', 956),
 ('PhD', 1207),
 ('master', 985)]
```