--- ###### tags: `Sprout` --- <style> .reveal { font-size: 32px; } </style> # Function ###### 資訊之芽py班 2023 ###### 黃千睿 --- ## Intro ---- ### 什麼是 function * 一系列動作的包裝 * 把動作定義好,方便後續使用 * 舉例來說,如果我要[畫一個圓](https://www.youtube.com/watch?v=EXNCQDi03mQ&ab_channel=95Ld) * 先畫一個頭 * 然後再擦掉一點點畫像的細部 * 然後1,2,3 * 一個圓,好了 ---- ![](https://i.imgur.com/0GlIcTK.png) ---- * 每次都要詳述流程很麻煩 * 我們就把這一系列動作包裝成「畫圓」 * function 就跟「畫圓」一樣,把一系列動作包裝起來 --- ## function 的語法 ---- ### 基本語法 ```python= def say_hello(): #函數名稱 print("Hello") #函數內容 say_hello() #呼叫函數 ``` ---- ### parameters & arguments * 如果我們希望 function 能根據不同的情形做不同的事情呢? * 可以善用 parameters(參數) 和 arguments(引數) ```python= def say_hello(a): print(f"Hello from {a}") say_hello("Enzo") ``` * 在這個例子中,a 就是parameter,"Enzo" 就是argument ---- * 一個 function 可以有多個參數,但需要注意他們的順序 ```python= def say_hello(a, b): print(f"Hello from {a} to {b}") say_hello("Alice", "Bob") ``` * 或是可以利用 key=value 的方式來表達,這樣就不用考慮順序 ```python= say_hello(a = "Alice", b = "Bob") say_hello(a = "Bob", b = "Alice") ``` ---- * 當我們把int, float, string 傳進 function 時,原本變數的值不會被改變 ```python= def f1(num): num += 1 x = 87 f1(x) print(x) ``` * 如果是 list, dict, set 等,則會改變原本的值 ```python= def f2(l): l[0] += 1 y = [87, 88, 89] f2(y) print(y) ``` ---- ### Why? * id() 回傳變數存在電腦內的位置 * 回傳的 id 一樣,代表我們會對存在在同個位置的同個東西操作 ```python= def f1(num): num += 1 print(f"id of num is {id(num)}") def f2(l): l[0] += 1 print(f"id of l is {id(l)}") x = 87 print(f"id of x is {id(x)}") f1(x) y = [87,88,89] print(f"id of y is {id(y)}") f2(y) print(x, y) ``` * 所以 function 內外的 list 其實是同一個 ---- ### 回傳值 * 如果想要讓 function 跑完可以產出一個值讓我們後續可以使用,那我們可以善用 function 的回傳值 (return value) ```python= def factorial(n): result = 1 for i in range(1, n + 1): result *= i return result print(factorial(5)/(factorial(2) * factorial(3))) ``` ---- * function 遇到 return 後就會直接中止,可以善用這個性質 ```python= def is_prime(number): for i in range(2, number): if number % i == 0: return False return True print(is_prime(17)) ``` ---- ### 定義 parameter 和 return value 的資料型態 ```python= def say_hello(a: str, b: str) -> str: print(f"Hello from {a} to {b}") say_hello("Alice", "Bob") ``` * python 不會檢查 parameter 和 return value 的資料型態是否如同宣稱 * 這個只是提供人類看得,python interpreter 不會理會 * 不知道大作業會不會用到 🙃 ---- ### 我們已經見過的 function 們 ```python= sum([1,2,3]) min(2,3) max(4,5) ``` ```python= type(sum) type(min) type(max) type(print) # builtin_function_or_method ``` ---- ### 練習 [比24還要好笑的笑話](https://neoj.sprout.tw/problem/3051) ---- ### 透過 function ,我們可以... 1. 把需要重複使用的一系列動作包裝起來 2. 呼叫 function 只需要知道它的參數、回傳值和功能是什麼,不用管function內部的實作方式 3. 讓你的程式變得更簡潔,別人也比較容易看懂 ```python= def factorial(n): result = 1 for i in range(1, n + 1): result *= i return result print(factorial(5)/(factorial(2) * factorial(3))) ``` ---- ### Questions? ---- ### 練習 [哪裡買TELSA電動車卡便宜](https://neoj.sprout.tw/problem/3005/) --- ## Recursive ---- ### Recursive (遞迴)的概念 * 在一個 function 內部呼叫自己 * 想想看費波納契數列的例子 ![](https://i.imgur.com/Bhd5zro.png) ---- 我們可以這樣做 ```python= def Fibonacci(n): if n == 0: return 0 if n == 1: return 1 return Fibonacci(n-1) + Fibonacci(n-2) ``` ---- ### 如果想要挑戰... [超級貓貓星際漫遊3](https://neoj.sprout.tw/problem/3403/) ---- ### Questions? --- ## Scope ---- ```python= s = 0 def plus(a,b): s = a + b print(f"s before plus: {s}") plus(1,2) print(f"s after plus: {s}") ``` 為什麼s沒有變化? ---- ### Scope (範圍) function 內的變數有兩種形式 * Global Variable(全域變數):所有地方都能看到的變數 * Local Variable(區域變數):只有 Function 裡面才能看到的變數 function 內的 local variable 跟外面是隔開的,雖然名字一樣但是互不干擾 ---- ```python= s = 0 def plus(a,b): s = a + b print(f"s before plus: {s}") plus(1,2) print(f"s after plus: {s}") ``` 所以在這個例子,plus() 中的 s 是 local variable,跟外面同樣名字的變數是隔開的 ---- ### 那什麼時候會出現 global variable 呢? ---- ### 官方說法 >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. [Reference]( https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python) ---- ![](https://i.imgur.com/A8My2Q8.png =400x) ---- ### 白話文 * 如果一個變數在function內沒有被賦值 (只有被reference),那它會被視為 global variable * 反之,它就是 local variable (除非他被特別宣告成 global variable) ---- ### 舉個栗子🌰 ```python= global_var = 1234 def func(): local_var = 5678 print(f"global = {global_var}, local={local_var}") func() print(f"global = {global_var}, local={local_var}") ``` 在這個例子中,global_var 就是全域變數,local_var 是區域變數 所以最後一行會出錯,因為 function 外看不到 local_var ---- ```python= s = 0 def plus(a,b): s = a + b print(f"s before plus: {s}") plus(1,2) print(f"s after plus: {s}") ``` 再回來看這個例子,因為 plus() 當中 s 這個變數被賦值了,所以就變成 local variable (就算外面也有s這個變數),跟外面同樣名字的變數是隔開的 ---- ```python= s = 0 def plus(a,b): global s s = a + b print(f"s before plus: {s}") plus(1,2) print(f"s after plus: {s}") ``` 我們也可以強制將應該是 local variable 的變數轉成 global variable ---- ### Questions? ---- ### 懂了之後,告訴你一個小秘密... 以上的狀況只適用於 int, float, bool 等基礎資料型態 至於 list, dict, set 這些資料型態基於跟 parameters & arguments 那段相同的原因,所以不適用 ---- ```python= s = [1,2,3] def plus(a,b): s[0] = a + b print(f"s before plus: {s}") plus(1,2) print(f"s after plus: {s}") ``` 像這樣 ---- * 盡可能避免使用 global variable,沒正確使用很容易變成地雷 * 如果你考上台大資工,大一修了P教授的計程,請記得不要在考試的時候使用全域變數 (會哭 🥺) ![](https://i.imgur.com/cqMfA8Z.png) --- ## Lambda Function ---- ### Lambda Function 的概念 假如我要寫一個回傳平方的 function ```python= def square(x): return x ** 2 print(square(4)) ``` 明明是很間單的運算,但是空間卻占的有點多 ---- ### Lambda Function 的概念 可以用 python 特別的lambda function 簡化 ```python= square = lambda x : x ** 2 print(square(4)) ``` 也可以有多個 parameter ```python= multiply = lambda a, b : a * b print(multiply(8,7)) ``` --- ## 作業 ---- 沒有作業,大作業加油🎉
{"metaMigratedAt":"2023-06-18T01:11:09.101Z","metaMigratedFrom":"Content","title":"Function","breaks":true,"contributors":"[{\"id\":\"12fd27f5-82a5-4f30-8a85-e747ae0676cf\",\"add\":6536,\"del\":462}]"}
    477 views