# 函式
#### 114/11/14
---
## 介紹函式
----
功能:將一段程式給予名稱並重複呼叫。
----
其實我們已經用過許多內建的函式
例如:`print()`、`input()`
今天會教大家如何定義函式
----
### 格式:
```python=
def 函式名稱(參數):
'''
程式
'''
return 回傳值
```
其中**參數**與 **return 回傳值**可以不寫
----
### 呼叫函式
將函式名稱打出來(要有括號)
```python
函式名稱(參數)
```
----
### 範例一
無參數
```py
def count_0_to_5():
for i in range(6):
print(i)
count_0_to_5()
```
----
### 範例二
```py=
def celsius_to_fahrenheit(c): #攝氏轉華氏
f = c * 9 / 5 + 32
print(f)
celsius_to_fahrenheit(0) #參數設為 0 (°C)
```
輸出:
```bash
32.0
```
----
### 小練習
寫一個函式, $x$ 為參數,輸出以下算式的結果。
$(x+1)(x+2)(x+3)$
----
### 解答
```python=
def f(x):
print((x + 1) * (x + 2) * (x + 3))
n = int(input())
f(n)
```
----
### 隨堂練習
請撰寫一個 `Python` 函式
`reverse_string(s)`,
該函式輸入一個字串 `s` 作為參數,
並返回該字串的反轉版本。
----
方法一
```python=
def reverse_string(s):
for i in range(len(s) - 1, -1, -1): #倒過來偵測
print(s[i], end="")
reverse_string(input())
```
方法二
```python=
def reverse_string(s):
print(s[::-1])
reverse_string(input())
```
忘了什麼是 `[::-1]` ?[看這裡](https://hackmd.io/@CRC-YUSHAN/ryb1DhYRlg#/6/7)
---
## 回傳值
----
#### 藉由`return`可以將函數執行結果回傳
#### 回傳值可以被儲存、列印
```python
def say_hello(name):
b = f"Hello, {name}!"
return b
```
```python
n = say_hello("Alice") #儲存回傳值
```
```python
print(say_hello("Alice")) #印出回傳值
```
----
若函式沒有 `return` ,會儲存成 $None$
```python
def say_hello(name):
b = f"Hello, {name}!"
```
```python
n = say_hello("Alice") #儲存為 None
```
----
### 例題一
請撰寫一個 `Python` 函式 `find_max_min(numbers)` ,該函式接受一個數字列表 `numbers` 作為參數,返回最大值和最小值`(Max, Min)`。如果列表為空,則返回 `(None, None)`。(本題以 `EOF` 結束)
> 忘記 `EOFError` 的人[點這裡](https://hackmd.io/@CRC-YUSHAN/r1leEJQkZg#/2)
----
範例輸入
```bash
3 1 4 1 5 9 2 6
-10 -20 0 5 3
#這行是沒東西
```
範例輸出
```bash
(9, 1)
(5, -20)
(None, None)
```
----
```py=
def find_max_min(numbers):
if not numbers: # 檢查列表是否為空
return (None, None)
max_value = max(numbers) # 找到最大值
min_value = min(numbers) # 找到最小值
return (max_value, min_value)
try:
while 1:
numbers = list(map(int, input().split()))
print(find_max_min(numbers))
except EOFError:
None
```
----
### 例題二
請寫一個 `Python` 函式 `calculate_average(args)` ,該函式接受多個數字作為參數,並返回這些數字的平均值(必為**整數**)。如果沒有提供任何數字,則返回 `0`。(本題以 `EOF` 結束)
> 提示:用 `sum()` 求總和;用 `len()` 求個數
----
解答
```py=
def calculate_average(args):
if not args:
return 0
return sum(args) // len(args)
try:
while 1:
numbers = list(map(int, input().split()))
print(calculate_average(numbers))
except EOFError:
None
```
---
## 變數範圍
----
### 變數的範圍(`scope`)主要有四種
1. **全域變數**(`Global Variables`)
2. **區域變數**(`Local Variables`)
3. 封閉變數(`Enclosing Variables`)
4. 內建變數(`Built-in Variables`)
----
### 全域變數(`Global Variables`)
在函數或類別外定義的變數。
在整個程式中都可以存取和修改。
```python=
x = 10 # 全域變數
def my_function():
print(x) # 可以在函數內部存取全域變數
my_function() # 輸出 10
```
----
### 區域變數(`Local Variables`)
在函數或類別方法內部定義的變數。
只能在定義區域內存取和修改。
```py=
def my_function():
y = 5 # 區域變數
print(y)
my_function() # 輸出 5
# print(y) # 錯誤, y 在函數外部不可見
```
----
當函數或方法執行完後,區域變數會被銷毀。
使用 `global` 關鍵字可以改成全域變數。
```py=
def my_function():
global y
y = 5
print(y)
my_function() # 輸出 5
print(y) # 輸出 5
```
----
### 【補充】封閉變數
### (`Enclosing Variables`)
在外層函數中定義的變數。
可以在內層函數中存取和修改。
使用 `nonlocal` 關鍵字可以在內層函數中存取和修改封閉變數。
----
範例
```python=
def outer_function():
x = 10 # 封閉變數
def inner_function():
y = 5 # 區域變數
print(x) # 可以存取封閉變數
inner_function()
outer_function() # 輸出 10
def modify_enclosing():
x = 10
def inner():
nonlocal x
x = 20 # 使用 nonlocal 關鍵字修改封閉變數
inner()
print(x) # 輸出 20
modify_enclosing()
```
----
### 內建變數(`Built-in Variables`)
即內建函式(`Built-in Functions`)
例如:`print()`
----
`Python` 會按照以下的搜尋順序來尋找變數:
1. 當前區域作用域( `Local` )
2. 封閉作用域( `Enclosing` )
3. 全域作用域( `Global` )
4. 內建作用域( `Built-in` )
如果在上述作用域中都找不到該變數,則會引發 `NameError` 異常。
----
### 觀念題
以下的輸出結果為何呢?
```py=
x = 5
def my_function():
x = 10
print(x)
my_function()
```
----
依據剛才的搜尋順序,結果為 `10` 。
---
## 預告
下週會教大家遞迴,
大家可以想想看 `return` 函數自己會發生什麼事
```python
def factorial(n):
if n == 1: # 終止條件
return 1
else:
return n * factorial(n - 1)
```
{"title":"函式","description":"EOFError、串列與迴圈、stack","slideOptions":"{\"theme\":\"sky\",\"transition\":\"convex\"}","contributors":"[{\"id\":\"b831f9fa-52bb-4a09-bfbb-148e4fdadd0f\",\"add\":4551,\"del\":183,\"latestUpdatedAt\":1763381100345}]"}