# Python 3 Fundamentals Week 16 - Functions 上 課程筆記

**URL:** https://vip.studycamp.tw/t/python-3-fundamentals-week-16-functions-%E4%B8%8A-%E8%AA%B2%E7%A8%8B%E7%AD%86%E8%A8%98/7136
**Category:** Python 3 Fundamentals
**Tags:** 上課筆記
**Created:** [2024年四月11日 11:08 UTC](https://vip.studycamp.tw/t/python-3-fundamentals-week-16-functions-%E4%B8%8A-%E8%AA%B2%E7%A8%8B%E7%AD%86%E8%A8%98/7136 "2024-04-11T11:08:45Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![Alice](https://vip.studycamp.tw/user_avatar/vip.studycamp.tw/alice/32/7353_2.png) [@Alice](https://vip.studycamp.tw/u/Alice)
#### Post date: [2024年四月11日 11:08 UTC](https://vip.studycamp.tw/t/python-3-fundamentals-week-16-functions-%E4%B8%8A-%E8%AA%B2%E7%A8%8B%E7%AD%86%E8%A8%98/7136/1 "2024-04-11T11:08:46Z")

</div>

# Introduction

## Why Use Functions in Python?

- Functions facilitate easy code re-use.
- They help break up complex code into easier-to-understand chunks.

## Parameter vs Argument

- **Parameter** : What is declared in the function definition.
- **Argument** : What is passed when calling the function.

## Functions as Python Objects

- Functions possess state (name, code, parameters, etc.).
- They are callable and always return something when called.
- Functions can be assigned to a symbol.
- They can be passed as parameters to other functions.
- Functions can be returned from a function call.

## Callables

- An object is callable if it can be invoked using `()`.
- Functions are called by invoking them, but other object types can also be callable.

```auto
# Calling Functions
print('hello')
math.sqrt(4)

# Calling a method on the object
my_list.copy()

# Calling the object itself - callable object 
range(100)

```

# Custom Functions

Functions are defined using the `def` keyword.

```auto
def function_name():
    # Indented block
    ...
    return <value>

```

- The `def` keyword signifies the definition of a function.
- The function’s name can be any valid Python identifier.
- The function body contains any valid Python code.
- Functions always return a value, defaulting to `None` if not specified.

## Example Without Return Value

```auto
def say_hello():
    print('Hello!')

result = say_hello()  
print(result)

# Output:
# Hello!
# None

```

## Example With Return Value

```auto
def one():
    return 1

result = one() 
print(result)

# Output:
# 1

```

## Passing Values to Functions (by Position)

```auto
def add(a, b): # Specify the parameters
    print(f'a = {a}')
    print(f'b = {b}')
    return a + b

add(2, 3)

# Output:
# a = 2
# b = 3
# 5

```

Positional arguments are passed in the order of parameters.

## Namespaces

> A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries. – Python glossary

 ![Example_Namespace](https://vip.studycamp.tw/uploads/default/original/2X/b/b146245d5230d3dd350b216eba4d49658d4616be.jpeg)

A namespace is created when a function is called, and it only lasts until the function returns.

## Coding

### Passing values as **named** arguments

```auto
def gen_matrix(rows, cols, default_value):
    return [[default_value for i in range(cols)] for j in range(rows)]

gen_matrix(cols=2, rows=2, default_value=1)

# Output:
# [[1, 1], [1, 1]]

```

### Passing values with a **mix** of positional and named arguments

```auto
def gen_matrix(rows, cols, default_value):
    return [[default_value for i in range(cols)] for j in range(rows)]

gen_matrix(2, cols=2, default_value=1)

# Output:
# [[1, 1], [1, 1]]

```

An error occurs due to multiple values assigned to the same argument:

```auto
def gen_matrix(rows, cols, default_value):
    return [[default_value for i in range(cols)] for j in range(rows)]

gen_matrix(1, rows=2, default_value=0)

```

Output:

```auto
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[11], line 4
      1 def gen_matrix(rows, cols, default_value):
      2 return [[default_value for i in range(cols)] for j in range(rows)]
----> 4 gen_matrix(1, rows=2, default_value=0)

TypeError: gen_matrix() got multiple values for argument 'rows'

```

Once passing value starts using named arguments in a call, all subsequent arguments must be named too:

```auto
def gen_matrix(rows, cols, default_value):
    return [[default_value for i in range(cols)] for j in range(rows)]

gen_matrix(2, rows=2, 0)

```

Output:

```auto
  Cell In[15], line 4
    gen_matrix(2, rows=2, 0)
                           ^
SyntaxError: positional argument follows keyword argument

```

# Star Arguments

When defining a function, the `*` can be used to capture an unlimited number of positional arguments given to the function. These arguments are captured into a tuple.

```auto
def average(*values):
    print(type(values))
    print(values)

average(1, 2, 3)

# Output:
# <class 'tuple'>
# (1, 2, 3)

```

### Using `*args` for an extra argument + variable number of arguments

```auto
def my_func(a, b, *others):
    print(a)
    print(b)
    print(others)

my_func(1, 2, 3, 4, 5)

# Output:
# 1
# 2
# (3, 4, 5)

```

```auto
def my_func(a, b, *others, c):
    print(a)
    print(b)
    print(others)
    print(c)

my_func(1, 2, 3, 4, 5)

```

Output:

```auto
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[5], line 7
      4 print(others)
      5 print(c)
----> 7 my_func(1, 2, 3, 4, 5)

TypeError: my_func() missing 1 required keyword-only argument: 'c'

```

```auto
def my_func(a, b, *others, c):
    print(a)
    print(b)
    print(others)
    print(c)

my_func(1, 2, 3, 4, c=5)

# Output:
# 1
# 2
# (3, 4)
# 5

```

### Using `*args` in Function Calls

When calling a function, the `*` can be used to unpack an iterable into the arguments in the function call.

```auto
def my_func(*numbers):
    print(numbers)
    for num in numbers:
        print(num)
    
L = [1, 2, 3]
my_func(L, 5)

# Output:
# ([1, 2, 3], 5)
# [1, 2, 3]
# 5

```

```auto
def my_func(*numbers):
    print(numbers)
    for num in numbers:
        print(num)
    
L = [1, 2, 3]
my_func(*L, 5)

# Output:
# (1, 2, 3, 5)
# 1
# 2
# 3
# 5

```
