# 2. Functions and Getting Help

## # Intro

In this lesson you will learn more about using and defining functions.

## # Getting Help

```
help(round)
```

`help()`

displays two things:

- the header of that function
`round(number[, ndigits])`

. In this case, this tells us that`round()`

takes an argument we can describe as`number`

. Additionally, we can optionally give a separate argument which could be described as`ndigits`

. - A brief English description of what the function does.

**Common pitfall:** when you're looking up a function, remember to pass in the name of the function itself, and not the result of calling that function, such as `help(round(-2.01))`

.

### # Defining functions

```
def least_difference(a, b, c):
diff1 = abs(a - b)
diff2 = abs(b - c)
diff3 = abs(a - c)
return min(diff1, diff2, diff3)
```

2

3

4

5

Functions start with a header introduced by the

`def`

keyword. The indented block of code following the`:`

is run when the function is called.

`return`

is another keyword uniquely associated with functions. When Python encounters a`return`

statement, it exits the function immediately, and passes the value on the right hand side to the calling context.

### # Docstrings(函数说明)

```
def least_difference(a, b, c):
"""Return the smallest difference between any two numbers
among a, b and c.
>>> least_difference(1, 5, -5)
4
"""
diff1 = abs(a - b)
diff2 = abs(b - c)
diff3 = abs(a - c)
return min(diff1, diff2, diff3)
```

2

3

4

5

6

7

8

9

10

11

The docstring is a triple-quoted string (which may span multiple lines) that comes immediately after the header of a function. When we call `help()`

on a function, it shows the docstring.

Aside: example callsThe last two lines of the docstring are an example function call and result. (The`>>>`

is a reference to the command prompt used in Python interactive shells.) Python doesn't run the example call - it's just there for the benefit of the reader. The convention of including 1 or more example calls in a function's docstring is far from universally observed, but it can be very effective at helping someone understand your function. For a real-world example of, see this docstring for the numpy function`np.eye`

(opens new window).

### # Functions that don't return

What would happen if we didn't include the `return`

keyword in our function?

```
def least_difference(a, b, c):
"""Return the smallest difference between any two numbers
among a, b and c.
"""
diff1 = abs(a - b)
diff2 = abs(b - c)
diff3 = abs(a - c)
min(diff1, diff2, diff3)
print(
least_difference(1, 10, 100),
least_difference(1, 10, 10),
least_difference(5, 6, 7),
)
```

2

3

4

5

6

7

8

9

10

11

12

13

14

Python allows us to define such functions. The result of calling them is the special value `None`

. (This is similar to the concept of "null" in other languages.)

Without a `return`

statement, `least_difference`

is completely pointless, but a function with side effects may do something useful without returning anything. We've already seen two examples of this: `print()`

and `help()`

don't return anything. We only call them for their side effects (putting some text on the screen). Other examples of useful side effects include writing to a file, or modifying an input.

```
mystery = print()
print(mystery)
```

2

### # Default arguments

```
print(1, 2, 3, sep=' < ')
```

if we don't specify a value, `sep`

is treated as having a default value of `' '`

(a single space).

```
print(1, 2, 3)
```

Adding optional arguments with default values to the functions we define turns out to be pretty easy:

```
def greet(who="Colin"):
print("Hello,", who)
greet()
greet(who="Kaggle")
# (In this case, we don't need to specify the name of the argument, because it's unambiguous.)
greet("world")
```

2

3

4

5

6

7

### # Functions Applied to Functions

You can supply functions as arguments to other functions.

```
def mult_by_five(x):
return 5 * x
def call(fn, arg):
"""Call fn on arg"""
return fn(arg)
def squared_call(fn, arg):
"""Call fn on the result of calling fn on arg"""
return fn(fn(arg))
print(
call(mult_by_five, 1),
squared_call(mult_by_five, 1),
sep='\n', # '\n' is the newline character - it starts a new line
)
```

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

Functions that operate on other functions are called "Higher order functions."

Here's an interesting example using the `max`

function.

By default, `max`

returns the largest of its arguments. But if we pass in a function using the optional `key`

argument, it returns the argument `x`

that maximizes `key(x)`

(aka the 'argmax').

```
def mod_5(x):
"""Return the remainder of x after dividing by 5"""
return x % 5
print(
'Which number is biggest?',
max(100, 51, 14),
'Which number is the biggest modulo 5?',
max(100, 51, 14, key=mod_5),
sep='\n',
)
```

2

3

4

5

6

7

8

9

10

11

## # Exercise: Functions and Getting Help

Functions open up a whole new world in Python programming. **Try using them yourself (opens new window)**

### # 1.

Complete the body of the following function according to its docstring.

```
def round_to_two_places(num):
"""Return the given number rounded to two decimal places.
>>> round_to_two_places(3.14159)
3.14
"""
# Replace this body with your own code.
# ("pass" is a keyword that does literally nothing. We used it as a placeholder
# because after we begin a code block, Python requires at least one line of code)
pass # we can delete pass here
return round(num,2)
q1.check()
```

2

3

4

5

6

7

8

9

10

11

12

13

### # 2.

The help for `round`

says that `ndigits`

(the second argument) may be negative.
What do you think will happen when it is? Try some examples in the following cell?

Can you think of a case where this would be useful?

```
# Put your test code here
round(322.1415, -2)
```

2

**Solution**: As you've seen, `ndigits=-1`

rounds to the nearest 10, `ndigits=-2`

rounds to the nearest 100 and so on. Where might this be useful? Suppose we're dealing with large numbers:

The area of Finland is 338,424 km² The area of Greenland is 2,166,086 km²

We probably don't care whether it's really 338,424, or 338,425, or 338,177. All those digits of accuracy are just distracting. We can chop them off by calling `round()`

with `ndigits=-3`

:

The area of Finland is 338,000 km² The area of Greenland is 2,166,000 km²

(We'll talk about how we would get the commas later when we talk about string formatting 😃)

### # 3.

In a previous programming problem, the candy-sharing friends Alice, Bob and Carol tried to split candies evenly. For the sake of their friendship, any candies left over would be smashed. For example, if they collectively bring home 91 candies, they'll take 30 each and smash 1.

Below is a simple function that will calculate the number of candies to smash for *any* number of total candies.

Modify it so that it optionally takes a second argument representing the number of friends the candies are being split between. If no second argument is provided, it should assume 3 friends, as before.

Update the docstring to reflect this new behaviour.

```
def to_smash(total_candies, n_friends=3):
"""Return the number of leftover candies that must be smashed after distributing
the given number of candies evenly between 3 friends.
>>> to_smash(91)
1
"""
return total_candies % n_friends
q3.check()
```

2

3

4

5

6

7

8

9

10

### # 4.

It may not be fun, but reading and understanding error messages will be an important part of your Python career.

Each code cell below contains some commented-out buggy code. For each cell...

- Read the code and predict what you think will happen when it's run.
- Then uncomment the code and run it to see what happens. (
**Tip**: In the kernel editor, you can highlight several lines and press`ctrl`

+`/`

to toggle commenting.) - Fix the code (so that it accomplishes its intended purpose without throwing an exception)

```
round_to_two_places(9.9999) # ruound_to_two_places(9.9999)
```

```
x = -10
y = 5
# Which of the two variables above has the smallest absolute value?
smallest_abs = min(abs(x), abs(y)) # smallest_abs = min(abs(x, y))
```

2

3

4

```
def f(x):
y = abs(x)
return y # SyntaxError: 'return' outside function
print(f(5))
```

2

3

4

5