# g.Python - 函式(Function) > <font color="#EA0000">**在某些程式語言中,沒有傳回值的就稱為「程序(Procedure)」,有回傳的就稱為「函式(Function)」**</font> > <font color="#EA0000">**但在Python中均稱為「函式(Function)」,如果函式沒有return,則會自動傳回'None'**</font> ###### tags: `Python` ## 1.函式的進階 * <font color="#0080FF">**用可變物件(mutable)作為引數**</font> ```python=+ def func(n,list1,list2): list1.append(3) #(更改陣列) list2 = [4,5,6] #(建立變數) n = n + 1 #(建立變數) x = 5 y = [1,2] z = [4,5] func(x,y,z) x,y,z #打包成tuple ``` > ```(5, [1, 2, 3], [4, 5])``` ## * <font color="#0080FF">**傳入可變物件如何不影響函式外部**</font> ```python=+ def func(list1): ls = list1[:] #在函式內複製一份可變物件即可 ls.append(3) x = [1,2] func(x) x ``` > ```[1, 2]``` ## * <font color="#0080FF">**<!>用可變物件作為參數預設值的問題**</font> ```python=+ def data_append(v,ls = []): #ls參照到可變的list物件,這個變數並不會隨著函式結束被刪除 ls.append(v) return ls data_append(3) data_append(5) ``` > ```[3]```</br> > ```[3,5]``` ## * <font color="#0080FF">**<!>用可變物件作為參數預設值的問題(續)**</font> ```python=+ def data_append(v,ls = None): #不要預設ls參照到可變物件即可 if(ls == None): ls = [] ls.append(v) return ls data_append(3) data_append(5) #不會有殘留值了 ``` > ```[3]```</br> > ```[5]``` ## 2. * 和 ** 的參數 * <font color="#0080FF">**'*' 用來接收多個引數 (打包成Tuple)**</font> ```python=+ def maximum(*num): if len(num) == 0: return None else: maxNum = num[0] for n in num: if n > maxNum: maxNum = n return maxNum maximum(1,3,5,4,2) #多個引數 maximum() #沒有引數也可以 ``` > ```5```</br> > ``` ``` ## * <font color="#0080FF">**<!> ** 用來接收多個指名引數 (打包成字典)**</font> ```python=+ def exam(x,*y,**other): result = ("x:{0}, y:{1} ,字典 'other' 內的鍵: {2}").format(x,y,list(other.keys())) return result exam(2,3,4,foo=3,bar=5) #多個指名引數 ``` > ```x:2, y:(3, 4) ,字典 'other' 內的鍵: ['foo', 'bar']``` ## 3.Lambda 匿名函式 * <font color="#0080FF">**lambda 匿名函式**</font> ```python=+ tt = {'FtoK':lambda deg_f:273.15 + (deg_f - 32) * 5/9, 'CtoK':lambda deg_c:273.15 + deg_c} print(tt['FtoK'](32)) #從字典查到'FtoK'這個key的值是lambda函式 print(tt['CtoK'](0)) #透過tt['CtoK']取得lambda函式 ``` > ```273.15```</br> > ```273.15``` ## * <font color="#0080FF">**lambda 匿名函式(續)**</font> ```python=+ word_list = ['Python','is','better','than','C'] word_list.sort(key = lambda s:len(s)) #word_list.sort(key = len) #這樣寫其實更好,因此濫用lambda可能影響程式可讀性 word_list ``` > ```['C', 'is', 'than', 'Python', 'better']``` ## 4.Generator 產生器(走訪器)函式 * <font color="#0080FF">**Yield 關鍵字傳回每次走訪的值**</font> ```python=+ def four(): x = 0 while x < 4: yield x x += 1 four() #產生器(走訪器)是特殊函式,要搭配For迴圈使用 list(four()) 2 in four() #可搭配'in'使用 ``` > ```<generator object four at 0x7ff72944fad0>```</br> > ```[0, 1, 2, 3]```</br> > ```True``` ## * <font color="#0080FF">**Yield 與 Yield from (自編範例)**</font> ```python=+ #yield from敘述從主產生器移到副產生器 def subgen(x): ls = [] for i in range(x): ls.append(i) yield ls #yield會在函式執行中回傳,因此ls不會消失 #主產生器 def gen(y): #執行subgen(6)並取得回傳值 yield from subgen(y) for q in gen(6): #從這裡開始 print(q) ``` > ```[0]```</br> > ```[0, 1]```</br> > ```[0, 1, 2]```</br> > ```[0, 1, 2, 3]```</br> > ```[0, 1, 2, 3, 4]```</br> > ```[0, 1, 2, 3, 4, 5]```</br> ## 5.Decorator 修飾器函式 * <font color="#0080FF">**修飾器(原始函式)**</font> > <font color="#EA0000">**當你想為函式新增功能,卻不想更動函式原始碼的情況下,就非常推薦使用修飾器!!**</font> > <font color="#EA0000">**函式是 Python 的 first-class object(第一級物件),</br>因此我們可以將函式指定給變數,也可作為引數傳遞給其他函式,甚至當作傳回值**</font> ```python=+ def friedchicken(): return 49.0 print(friedchicken()) #49.0 ``` >```49.0``` ## * <font color="#0080FF">**<!>修飾器(新增功能)**</font> ```python=+ def sidedish1(meal): return lambda: meal() + 30 #回傳為函式(lambda) #return meal() + 30 #這樣寫會變成回傳數值(float) def friedchicken(): return 49.0 #修飾器敘述 friedchicken = sidedish1(friedchicken) #(!)注意 friedchicken 還是一個函式!! print(friedchicken()) #新的friedchicken函式 ``` >```79.0``` ## * <font color="#0080FF">**<!>修飾器(語法糖)**</font> ```python=+ def sidedish1(meal): return lambda: meal() + 30 @sidedish1 #等同「friedchicken = sidedish1(friedchicken)」 def friedchicken(): return 49.0 print(friedchicken()) #新的friedchicken函式 ``` >```79.0``` ## 6.global、nonlocal、local變數 | 類型 | 說明 | | :------: | :-----------: | | **global** | 宣告「全域變數」 | | **nonlocal** | 宣告「上一層變數」 | | **local** | 宣告「區域變數」 | * <font color="#0080FF">**用global宣告全域變數**</font> ```python=+ def func(): global a #宣告a為全域變數 a = "local" b = "local" a = "global" b = "global" func() print("a:",a) print("b:",b) ``` ## * <font color="#0080FF">**global 與 nonlocal 的位置**</font> ```python=+ def func(): a = 1 nonlocal a #a已經被視為local區域變數,不能再宣告為nonlocal或global ``` > ```SyntaxError: name 'a' is assigned to before nonlocal declaration``` ## * <font color="#0080FF">**local區域變數未賦值先用**</font> > <font color="#EA0000">**只要在函式內部(不論位置)對該變數有賦值動作,該變數一律視為local區域變數**</font> ```python=+ a = "global" def func(x): if x: a = "local" #變數a在函式(func)有賦值動作,視為區域變數,因此不會往外找 print(a) func(True) func(False) ``` > ```local```</br> > ```local variable 'a' referenced before assignment``` ## 時間戳記 > [name=ZEOxO][time=Mon, Aug 30, 2020 23:00 PM][color=#907bf7]