Function
資訊之芽py班 2023
黃千睿
什麼是 function
一系列動作的包裝
把動作定義好,方便後續使用
舉例來說,如果我要 畫一個圓
先畫一個頭
然後再擦掉一點點畫像的細部
然後1,2,3
一個圓,好了
每次都要詳述流程很麻煩
我們就把這一系列動作包裝成「畫圓」
function 就跟「畫圓」一樣,把一系列動作包裝起來
基本語法
def say_hello ():
print ("Hello" )
say_hello()
parameters & arguments
如果我們希望 function 能根據不同的情形做不同的事情呢?
可以善用 parameters(參數) 和 arguments(引數)
def say_hello (a ):
print (f"Hello from {a} " )
say_hello("Enzo" )
在這個例子中,a 就是parameter,"Enzo" 就是argument
一個 function 可以有多個參數,但需要注意他們的順序
def say_hello (a, b ):
print (f"Hello from {a} to {b} " )
say_hello("Alice" , "Bob" )
或是可以利用 key=value 的方式來表達,這樣就不用考慮順序
say_hello(a = "Alice" , b = "Bob" )
say_hello(a = "Bob" , b = "Alice" )
當我們把int, float, string 傳進 function 時,原本變數的值不會被改變
def f1 (num ):
num += 1
x = 87
f1(x)
print (x)
如果是 list, dict, set 等,則會改變原本的值
def f2 (l ):
l[0 ] += 1
y = [87 , 88 , 89 ]
f2(y)
print (y)
Why?
id() 回傳變數存在電腦內的位置
回傳的 id 一樣,代表我們會對存在在同個位置的同個東西操作
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)
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 後就會直接中止,可以善用這個性質
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 的資料型態
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 們
sum ([1 ,2 ,3 ])
min (2 ,3 )
max (4 ,5 )
type (sum )
type (min )
type (max )
type (print )
透過 function ,我們可以 …
把需要重複使用的一系列動作包裝起來
呼叫 function 只需要知道它的參數、回傳值和功能是什麼,不用管function內部的實作方式
讓你的程式變得更簡潔,別人也比較容易看懂
def factorial (n ):
result = 1
for i in range (1 , n + 1 ):
result *= i
return result
print (factorial(5 )/(factorial(2 ) * factorial(3 )))
Recursive (遞迴)的概念
在一個 function 內部呼叫自己
想想看費波納契數列的例子
我們可以這樣做
def Fibonacci (n ):
if n == 0 :
return 0
if n == 1 :
return 1
return Fibonacci(n-1 ) + Fibonacci(n-2 )
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 跟外面是隔開的,雖然名字一樣但是互不干擾
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
白話文
如果一個變數在function內沒有被賦值 (只有被reference),那它會被視為 global variable
反之,它就是 local variable (除非他被特別宣告成 global variable)
舉個栗子🌰
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
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這個變數),跟外面同樣名字的變數是隔開的
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
懂了之後,告訴你一個小秘密 …
以上的狀況只適用於 int, float, bool 等基礎資料型態
至於 list, dict, set 這些資料型態基於跟 parameters & arguments 那段相同的原因,所以不適用
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教授的計程,請記得不要在考試的時候使用全域變數 (會哭 🥺)
Lambda Function 的概念
假如我要寫一個回傳平方的 function
def square (x ):
return x ** 2
print (square(4 ))
明明是很間單的運算,但是空間卻占的有點多
Lambda Function 的概念
可以用 python 特別的lambda function 簡化
square = lambda x : x ** 2
print (square(4 ))
也可以有多個 parameter
multiply = lambda a, b : a * b
print (multiply(8 ,7 ))
Resume presentation
Function 資訊之芽py班 2023 黃千睿
{"metaMigratedAt":"2023-06-18T01:11:09.101Z","metaMigratedFrom":"Content","title":"Function","breaks":true,"contributors":"[{\"id\":\"12fd27f5-82a5-4f30-8a85-e747ae0676cf\",\"add\":6536,\"del\":462}]"}