Skip to content
Snippets Groups Projects
Commit 2d5169bf authored by LOUIS TYRRELL OLIPHANT's avatar LOUIS TYRRELL OLIPHANT
Browse files

lec 6 creating functions

parent 37f6b117
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:review
## Warmup
%% Cell type:code id: tags:review
``` python
# Warmup 1
# Get the user's name using the input function.
# Then, print out 'Hello, NAME'
```
%% Cell type:code id: tags:review
``` python
# Warmup 2
# Ask the user for a number, then tell them the sqrt of it.
# HINT: sqrt needs to be imported from math!
```
%% Cell type:code id: tags:review
``` python
# Warmup 3
# Fix the code below. What type of error(s) did you fix?
x = input("Tell me a number! ")
is-even = (x % 2 == 0)
print("That number is even: " + is-even)
```
%% Cell type:code id: tags:review
``` python
# Warmup 4
# TODO: For this code to work, on the line below, import the time module
start_time = time.time()
x = 2**1000000000 # a very long computation
end_time = time.time()
difference = end_time - start_time
# Seperate each time with a '\n'
print(start_time, end_time, difference,sep="\n")
```
%% Cell type:code id: tags:review
``` python
# Warmup 5
# TODO: Run help on the time.time function to see what it does
help()
```
%% Cell type:code id: tags:review
``` python
# Warmup 6
# TODO: From the math module, import only the log10 function
# Then, print the log base 10 of 1000
print(log10(1000))
```
%% Cell type:code id: tags:review
``` python
# Warmup 7
# This one is done for you as an example!
# Note: importing with 'wildcard' * is generally considered bad practice
from math import * # allows us to use all functions without writing math
print(pi)
```
%% Output
3.141592653589793
%% Cell type:code id: tags:review
``` python
# Warmup 8
# TODO: Try importing and printing 'pi' the proper way (only importing that one thing from the module)!
# Add import statement here
print(pi)
```
%% Cell type:markdown id: tags:review
## Reminder
- Use `sep` and `end` keywords in print() function
- Use correct vocabulary when talking about functions (definition, call/invoke, parameter, argument, keyword argument, return value)
- Use common built-in functions (`input()`, `round()`, `abs()`, `type()`, `len()`, `print()`)
- Get help using both `help()` and `dir()`
- Use type cast functions to convert between types (`int()`, `bool()`, `float()`, `str()`)
- Import modules in 3 different ways (`import <module>`, `from <module> import <function>`, and `from <module> import *`
- Use imported functions properly (either using `.` (dot) notation or calling function directly)
- Be able to change the cell types (Markdown, Cell, and Raw), and important properties (read-only vs. editable) of a cell
%% Cell type:markdown id: tags:
# Creating Functions
## Readings
- [Finish Chapter 3 of Think Python](https://greenteapress.com/thinkpython2/html/thinkpython2004.html),
- [Chapter 5.5 to 5.8 of Python for Everybody](https://runestone.academy/ns/books/published//py4e-int/functions/toctree.html)
- [Creating Fruitful Functions](https://cs220.cs.wisc.edu/f24/materials/lecture_ppts/lec-06-extra.pdf)
%% Cell type:markdown id: tags:
## Learning Objectives
- Explain the syntax of a function header:
- def, ( ), :, tabbing, return
- Write a function with:
- correct header and indentation
- a return value (fruitful function) or without (void function)
- parameters that have default values
- Write a function knowing the difference in outcomes of print and return statements
- Explain how positional, keyword, and default arguments are copied into parameters
- Make function calls using positional, keyword, and default arguments and determine the result.
- Use the debugger to trace function invocations to determine control flow
%% Cell type:markdown id: tags:
## Functions
A function definition has two parts:
- **head** or **header** - the line that begins a function definition. It must be of the form:
`def <func_name>(parameters):`
`parameters` may be empty or it may be a comma-separated list of variables. The values these variables will refer to will be passed in when the function call occurs.
`<func_name>` must follow the same naming rules as variables. Typically function names are verbs while variable names are nouns.
- **body** - the rest of the function definition, consisting of lines of code. These lines must be indented.
The full function definition has the form:
```
def <func_name>(parameters):
body_line1
body_line2
...
```
%% Cell type:code id: tags:
``` python
# TODO: Write a function named cube that takes one number input and cubes and return that value
# The first line is called the function header
# Notice that all the other lines are indented the same amount (4 spaces)
# The best practice in a Jupyter Notebook is to press tab
# If you don't run the cell, Jupyter Notebook won't know about the function
# Open the debugger and notice what is created in the kernel state when this cell runs
# Look under the "function variables" section
```
%% Cell type:code id: tags:
``` python
# Now we call or invoke the cube function! Run the code below:
print(cube(5))
print(cube(4)+cube(-3))
print(cube(cube(2)))
```
%% Cell type:code id: tags:
``` python
# In the bad_cube function definition in this cell the parameter is cubed and printed rather than returned
# this is bad practice.
def bad_cube(num):
print(num ** 3)
```
%% Cell type:code id: tags:
``` python
# Explain what goes wrong in these function calls.
x = bad_cube(5) #bad_cube does not return anything (it prints a value, but doesn't return a value)
print(x) #since nothing is returned, x contains the value None and that is what is printed
```
%% Cell type:markdown id: tags:
## `return` vs `print`
- `return` enables us to send output from a function to the calling place
- default `return` value is `None`
- that means, when you don't have a `return` statement, `None` will be returned
- `print` function simply displays / prints something
- it cannot enable you to produce output from a function
%% Cell type:code id: tags:
``` python
# TODO: Write a function that determines if one number is strictly between two other numbers
# return a boolean ... True or False
# delete the "pass" line of code and put your own code there
def is_between(lower, num, upper):
pass
# you can call a function in the same cell that you defined it
print(is_between(5,8,13))
print(is_between(5,5,13))
print(is_between(100,cube(5),200))
```
%% Cell type:code id: tags:
``` python
# Example 3: write a function get_grid that works like this:
# get_grid(5, 3, "@") returns the string
# @@@@@
# @@@@@
# @@@@@
# Let's practice Incremental Coding
# first, try to do this with string operators and literals
print((("#" * 5) + '\n') * 3)
```
%% Cell type:code id: tags:
``` python
# then, try to do this with variables
width = 5
height = 3
symbol = '#'
print(((symbol * width) + '\n') * height)
```
%% Cell type:code id: tags:
``` python
# now, try to write a function
# think about what would be good names for the parameters
def get_grid(width, height, symb):
return (((symb * width) + '\n') * height)
my_grid = get_grid(5, 3, "*");
# do some code
2**1000000000
# ...
print(my_grid)
```
%% Cell type:code id: tags:
``` python
# Finally, add in a parameter for a title that appears above the grid
def get_grid_with_title(width, height, symb, title='My Grid'):
row = (symb * width) + '\n'
grid = ((row) * height)
return title + '\n' + grid
```
%% Cell type:code id: tags:
``` python
# TODO: now run the function. Try using different input values.
print(get_grid_with_title(7, 7, title='CS220 Grid', symb='&'))
```
%% Cell type:markdown id: tags:
## Types of arguments
- positional
- keyword
- default
Python fills arguments in this order: positional, keyword,
%% Cell type:code id: tags:
``` python
def add3(x, y = 100, z = 100):
"""adds three numbers""" #documentation string
tot = x + y + z
return tot
#calls function with position arguments
addition_of_3 = add3(100, 10, 5)
print(addition_of_3)
help(add3)
```
%% Cell type:code id: tags:
``` python
print(add3(x = 1, z = 2, y = 5)) #calls function with keyword arguments
```
%% Cell type:code id: tags:
``` python
add3(5, 6) # calls function using positional arguments and one default value argument
```
%% Cell type:markdown id: tags:
Positional arguments need to be specified before keyword arguments.
%% Cell type:code id: tags:
``` python
# Incorrect function call
add3(z = 5, 2, 7)
# TODO: what category of error is this?
```
%% Cell type:code id: tags:
``` python
# Incorrect function definition
# We must specify non-default arguments first
def add3_bad_version(x = 10, y, z):
"""adds three numbers""" #documentation string
return x + y + z
```
%% Cell type:code id: tags:
``` python
# Incorrect function call
add3(5, 3, 10, x = 4)
# TODO: what category of error is this?
```
%% Cell type:code id: tags:
``` python
# TODO: will this function call work?
add3(y = 5, z = 10)
```
%% Cell type:code id: tags:
``` python
# TODO: will this function call work?
add3()
```
%% Cell type:markdown id: tags:
## fruitful function versus void function
- fruitful function: returns something
- ex: add3
- void function: doesn't return anything
- ex: bad_add3_v1
%% Cell type:code id: tags:
``` python
# Example of void function
def bad_add3_v1(x, y, z):
print(x + y + z)
print(bad_add3_v1(4, 2, 1))
```
%% Cell type:code id: tags:
``` python
print(bad_add3_v1(4, 2, 1) ** 2) # Cannot apply mathematical operator to None
```
%% Cell type:markdown id: tags:
### `return` statement is final
- exactly *one* `return` statement gets executed for a function call
- immediately after encountering `return`, function execution terminates
%% Cell type:code id: tags:
``` python
def bad_add3_v2(x, y, z):
return x
return x + y + z # will never execute
bad_add3_v2(50, 60, 70)
```
%% Cell type:markdown id: tags:
## Tracing Code Execution Using the Debugger
Tracing code is the process of working through by hand the order that lines of code will be executed. A debugger can be very helpful in this process.
1. Turn on the debugger and open the debugger sidepanel.
![image.png](attachment:b25aea2c-891f-447e-a405-91fa95ba1b27.png)
2. Add a breakpoint to your code. Do this by clicking on the line number of a line of code within the cell. A red dot should appear next to that line of code. Now, when you run the code in the cell when that line is reached the debugger will stop executing your code.
![image.png](attachment:f3649896-c4f8-4e83-a695-8c629044e611.png)
3. Click the run button (or press shift-enter) to start running the code in the cell. The code will run up to the line where you added a breakpoint and will then stop.
4. Use the buttons in the bebugger sidepanel next to the "callstack" section in the side panel to control the continued execution of the code:
- ![image.png](attachment:d4c26cbe-f2b6-477f-960b-1758b11853e0.png) (**next**) - Run the next line of code.
- ![image.png](attachment:5cd6164b-a7da-414b-8b42-1ff682e50ace.png) (**step-into**) - If a line of code calls a function, go into that function stop on the first line of code within the function.
- ![image.png](attachment:2d33f283-d329-4087-96d7-2908f34cd33e.png) (**step-out**) - Execute all lines of code of the function you are currently in and stop at the first line of code outside of the function.
- ![image.png](attachment:e535eef7-4136-4ece-a1fd-f4d4f3259ad5.png) (**continue**) - Run the code until you reach the next breakpoint
- ![image.png](attachment:0763ccd8-a625-4ac5-83e6-32f7a5e2dbb5.png) (**terminate**) - stop running the code.
Be aware if the buttons are greyed out or not. This is another way you can tell if the kernel is still busy trying to execute the code in the cell. Even after every line of code in the cell has finished executing, you will still need to continue stepping until the kernel is free (or you can click the stop button).
![image.png](attachment:fc577085-ab22-4961-ad11-7ef72fca0505.png) (kernel is still busy with the code in the cell)
![image.png](attachment:a3c30096-71b3-4281-95b3-fa0cf967bbc9.png) (kernel has finished executing the code in the cell)
Follow along as we use the debugger on the code cell below.
%% Cell type:code id: tags:
``` python
def func_c():
print("C")
def func_b():
print("B1")
func_c()
print("B2")
def func_a():
print("A1")
func_b()
print("A2")
func_a()
```
%% Cell type:markdown id: tags:
## You Try It
For the code cells below, can you think through what will be printed, and in what order? Use the debugger to set a breakpoint and step through the lines of code and see if it is executed and the output is printed in the order that you thought.
%% Cell type:code id: tags:
``` python
print("A")
def foo():
print("B")
print("C")
foo()
print("D")
foo()
```
%% Cell type:code id: tags:
``` python
#Almost the same as the last cell but the print("C") has been indented
print("A")
def foo():
print("B")
print("C")
foo()
print("D")
foo()
```
%% Cell type:code id: tags:
``` python
def f():
print("A")
return "B"
print("C")
print("D")
x = f()
print("E")
print(x)
```
%% Cell type:markdown id: tags:
## Summary
You have learned how to **define a function** and what the different portions of the definition are called (header, body, parameters, default value, return). You know how to **pass values by position, keyword, or use the default value**. You know the difference between and **fruitful function and a void function** and the difference between using a print statement and a return statement. You have practiced **using the debugger to step through execution** of Python code.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment