# Function By 楊翔宇 (極速車神大佬) --- ## 什麼是 Function ? ---- ### 國中學過的 Function: $f(x) = 3x^2 + 5x - 7$ $f(2) = ?$ - 代入 2 - 得到 $f(2) = 3 \cdot 2^2 + 5 \cdot 2 - 7 = 15$ ---- ### 程式的 Function 又是什麼 ? - 不只是數字運算,還是一系列程式碼的包裝 - 舉個做菜的例子 - 做菜的 Function 可能叫做 `make_pasta()` - 這個 Function 可能包含了以下步驟: 1. 煮水 2. 加入義大利麵 3. 煮到軟硬適中 4. 撈起來瀝乾 5. 加入醬料再炒一次 ---- ### 為什麼要使用 function (?) - 可以讓程式碼更簡潔、重複用很方便 - 要煮很多次義大利麵的話... - 有很多別人寫好的 function! - 例如:`print()`, `input()`, `len()`, `range()`, `math.sqrt()`, ... - 或者你跟別人一起寫,大家都寫 function,這樣就可以互相呼叫對方的 function --- ## Function 的語法 ---- ```python def function_name(parameters): # function body return result ``` - `def` 是定義 function 的關鍵字 - `function_name` 是 function 的名稱,可以自己取 - `parameters` 是 function 的參數,可以有多個,也可以沒有 - `function body` 是 function 的內容,可以是多行程式碼 - `return` 是 function 的回傳值,可以沒有 ---- ### 使用方法 用剛才的 $f(x)$ 舉個例子: 注意 function 的建立和使用是分開的,先建立 function 再使用 ```python def f(x): result = 3 * x * x + 5 * x - 7 return result print(f(2)) # 輸出 15 ``` ---- ### Argument (參數) & Parameter (引數) 在 function 中,argument 跟 parameter 可以讓我們在不同的情況下做不同的事情 - Parameter 是 function 定義時的變數名稱 - Argument 是 function 呼叫時傳入的值 ```python def f(x): result = 3 * x * x + 5 * x - 7 return result print(f(2)) # 輸出 17 ``` - 在這裡,`x` 是 parameter,而 `2` 是 argument ---- Argument 跟 parameter 可以沒有,也可以有多個,但是要注意順序和數量要對應 ```python def f(x, y): result = 3 * x * x + 5 * y - 7 return result print(f(2, 3)) # 輸出 20 ``` - 在這裡,`x` 和 `y` 是 parameters,而 `2` 和 `3` 是 arguments ---- 練習 [比24還要好笑的笑話](https://tioj.sprout.tw/contests/51/problems/711) ---- ### Return value (回傳值) Return value 是 function 執行完後回傳的結果,可以讓我們在其他地方使用這個結果。 也可以沒有 return value,如果沒有 return value,預設會回傳 `None` ---- ```python def f(x): return 3 * x * x + 5 * x - 7 result = f(2) # Return value 是 15 print(result) # 輸出 15 ``` 如果沒有回傳值: ```python def f(x): print(3 * x * x + 5 * x - 7) result = f(2) # Return value 是 None print(result) # 輸出 None ``` ---- ### 也可以有多個 其實就是回傳一個 tuple ```python def f(x): return 3 * x * x + 5 * x - 7, 2 * x + 1 result = f(2) # Return value 是 (15, 5) print(result) # 輸出 (15, 5) ``` ---- 練習 [哪裡買TELSA電動車卡便宜](https://tioj.sprout.tw/contests/51/problems/666) --- ## 更多關於 Function ### Default argument 我們可以在建立 function 的時候設定 default argument,這樣可以用較少的 parameter 來呼叫 function ```python def f(x, y=0): return 3 * x * x + 5 * y - 7 print(f(2)) # 輸出 5,因為 y 預設為 0 print(f(2, 3)) # 輸出 20,因為 y 被設定為 3 ``` ---- 要注意 default argument 的位置,必須放在 non-default argument 的後面 ```python def f(x=0, y): return 3 * x * x + 5 * y - 7 ``` 會拿到 `SyntaxError: parameter without a default follows parameter with a default` ---- ### Keyword argument 我們可以在使用 function 的時候用 `kwarg=value` 的方式來指定 argument,這樣就不需要按照 parameter 的順序來傳入 argument,而且也更清楚 ```python def f(x, y=1, z=2): return 3 * x * x + 5 * y - z print(f(2)) # 輸出 15,因為 y 預設為 1,z 預設為 2 print(f(2, z=3)) # 輸出 14 print(f(2, y=4, z=5)) # 輸出 27 ''' 不正確的用法 f() # TypeError: f() missing 1 required positional argument: 'x' f(z=3) # TypeError: f() missing 1 required positional argument: 'x' f(y=4, 2) # SyntaxError: positional argument follows keyword argument ''' ``` --- ## Recursion (遞迴) 可以在 function 裡面呼叫自己 ! 用費氏數列 $1, 1, 2, 3, 5...$ 作為例子 ```python def fibonacci(n): if n == 1 or n == 2: return 1 else: return fibonacci(n - 1) + fibonacci(n - 2) print(fibonacci(5)) # 輸出 5 ``` ---- 解析一下: - fibonacci(5) 會呼叫 fibonacci(4) 和 fibonacci(3) - fibonacci(4) 會呼叫 fibonacci(3) 和 fibonacci(2) - fibonacci(3) 會呼叫 fibonacci(2) 和 fibonacci(1) - fibonacci(2) 會回傳 1 - fibonacci(1) 會回傳 1 - fibonacci(2) 會回傳 1 - fibonacci(3) 會回傳 fabonacci(2) + fibonacci(1) = 1 + 1 = 2 - fibonacci(4) 會回傳 fibonacci(3) + fibonacci(2) = 2 + 1 = 3 - fibonacci(5) 會回傳 fibonacci(4) + fibonacci(3) = 3 + 2 = 5 ---- 這裡帶大家用遞迴寫一個 $1+2+3+...+n$ 的 function ```python def sum_n(n): if n == 0: return 0 else: return n + sum_n(n - 1) print(sum_n(5)) # 輸出 15 ``` ---- ### 小練習 [[超簡單] 階乘?](https://tioj.sprout.tw/contests/51/problems/99) --- ## 變數 scope ---- 變數主要有分 Local 跟 Global 官方說法: > What are the rules for local and global variables in Python? In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function’s body, it’s assumed to be a local unless explicitly declared as global. ---- > 怎麼分辨 local 跟 global 變數呢?如果在 function 裡面只有被 reference 過的話,那會是 global。如果有在 function 裡面被 assign 的話,那是 local,除非你在 function 裡面用 `global` 關鍵字宣告它是 global。 ---- global 代表這個變數跟 function 外的變數是同個東西,如果更改了這個變數的值,那 function 外的變數也會跟著改變。local 變數沒有這種特性。 這裡的 reference 跟 assign 又分別是什麼? ---- ```python x = 3 def set_x(): x = 4 # 這裡是 assign,因為我們給 x 一個新的值 4,所以 x 是 local 變數 set_x() print(x) # 還是輸出 3 ``` ---- ```python x = 3 def set_x(): global x x = 4 # 這裡是 assign,但因為我們明確使用 `global` 關鍵字,所以 x 是 global 變數 set_x() print(x) # 輸出 4 ``` ---- id() 可以確認變數的記憶體位置,global 變數的 id() 是不會改變的,而 local 變數的 id() 是會改變的。 ---- ```python x = 3 def set_x(): x = 4 # 這裡是 assign,因為我們給 x 一個新的值 4,所以 x 是 local 變數 print(f'Function 裡面 x 的 id: {id(x)}') # local x 的 id print(f'Function 外面 x 執行 set_x () 前的 id: {id(x)}') # global x 的 id set_x() print(f'Function 外面 x 執行 set_x () 後的 id: {id(x)}') # global x 的 id print(x) # 還是輸出 3 ``` ---- ```python x = 3 def set_x(): global x x = 4 # 這裡是 assign,因為我們給 x 一個新的值 4,所以 x 是 global 變數 print(f'Function 裡面 x 的 id: {id(x)}') # global x 的 id print(f'Function 外面 x 執行 set_x () 前的 id: {id(x)}') # global x 的 id set_x() print(f'Function 外面 x 執行 set_x () 後的 id: {id(x)}') # global x 的 id print(x) # 輸出 4 ``` ---- ```python x = 3 def set_x(x): print(f'Function 裡面 assign x 前的 id: {id(x)}') # 這裡還是 global x = 4 # 這裡是 assign,所以 x 是 local 變數 print(f'Function 裡面 assign x 後的 id: {id(x)}') # local x 的 id print(f'Function 外面 x 執行 set_x () 前的 id: {id(x)}') # global x 的 id set_x() print(f'Function 外面 x 執行 set_x () 後的 id: {id(x)}') # global x 的 id print(x) # 還是輸出 3 ``` --- ## Mutable 跟 Immutable 的變數 前幾堂課有提過! 我們來講在 function 裡面 mutable 跟 immutable 變數的差異 ---- ```python def add(x): x = x + 1 # 這裡是 assign,因為我們給 x 一個新的值,所以 x 是 local 變數 x = 3 add(x) print(x) # 輸出 3 ``` ---- 但是如果我們用 mutable 的變數呢? ```python def append_list(l): l.append(4) # 這裡是 reference,因為我們沒有給 l 一個新的值,而是對 l 做修改,所以 l 是 global 變數 l = [1, 2, 3] append_list(l) print(l) # 輸出 [1, 2, 3, 4] ``` ---- 因此要注意! 並不是所有在 function 裡面被 assign 的變數都是 local 變數,如果是 mutable 的變數,就算是 reference,還是會影響到 global 變數的值。 --- ## lambda function ---- 基本上就是一個沒有名字的 function,可以用來寫一些簡單的 function ```python def multiply_type1(x, y): return x * y multiply_type2 = lambda x, y: x * y print(multiply_type1(2, 3)) # 輸出 6 print(multiply_type2(2, 3)) # 輸出 6 ``` ---- 也可以搭配參數傳遞 (一般來說 lambda function 會用在一些需要 function 作為參數的情況) ```python def apply_function(func, x, y): return func(x, y) def multiply_type1(x, y): return x * y print(apply_function(multiply_type1, 2, 3)) # 輸出 6 print(apply_function(lambda x, y: x * y, 2, 3)) # 輸出 6 ``` --- ## 結語 function 其實大家現在看起來不像是一個很有用的東西 確實他沒有立即性的幫助,但 function 卻是在真實世界程式裡面不可或缺的元素! (個人認為重要的點在於把一大串程式碼包成 function 可以很方便的管理!) <style> @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Noto+Sans+TC:wght@100..900&display=swap'); :root { --r-code-font: "JetBrains Mono", monospace; --r-main-font: "Inter", "Noto Sans TC", sans-serif; --r-heading-font: "Inter", "Noto Sans TC", sans-serif; --r-heading-text-transform: none; --r-main-font-size: 32px; } .reveal-viewport { backdrop-filter: blur(64px); background: radial-gradient(circle at top left, #3398, #0000 50%), radial-gradient(circle at bottom right, #9938, #0000 50%), #000d; } .reveal .slides { text-align: left; } .reveal .slides .slide:not(.title-slide) { height: 80%; } .reveal .slides .slide .slide-body { height: 80%; display: flex; flex-direction: column; justify-content: center; } .reveal div.sourceCode { margin: 0; min-height: 0; background: transparent; display: flex; flex-direction: column; } .reveal pre { all: unset; min-height: 0; display: flex; flex-direction: column; } .reveal code { font-size: .8em; padding: .2em; border: 1px solid #fff3; border-radius: .2em; background-color: #0003; } .reveal .sourceCode code { font-size: .6em; padding: 1em; overflow: scroll; } .reveal blockquote { display: flex; flex-direction: column; background: transparent; box-shadow: none; } .reveal blockquote p { margin: 0; } .reveal blockquote::before { content: "❝"; font-size: 2em; line-height: 0; margin-left: -1em; margin-bottom: -.25em; } .reveal blockquote::after { content: "❞"; font-size: 2em; line-height: 0; text-align: right; } .reveal blockquote + p { text-align: right; } </style>
{"title":"Function","description":"Here is the cleaned Markdown version of the presentation with all the `` tags removed.","contributors":"[{\"id\":\"6a375517-4167-4b7c-a983-1e595a29262c\",\"add\":23972,\"del\":14945,\"latestUpdatedAt\":1774163446207}]"}
    41 views