Try   HackMD

Python function 函式呼叫 / 錯誤例外處理 exception

學習如何看懂Python官方手冊,以及語法規則,職訓所課堂筆記。


臨時整理區:

魔法函式
__name__ == "__main__" 直接執行而非被載入

https://pythonbook.cc/chapters/basic/module-and-package#被匯入-vs-直接執行


呼叫規則

先定義好 function

def func(區域參數):
    主要程式
    return 返回值

# 參數可設預設值,必須固定值 def twoSum(a, b = 5): """ 兩個數字加起來 """ c = a + b return c

調用函式

# 參數傳遞 a,b a, b = 2, 3 ans = twoSum(a, b) print(ans)

局部引數

def print_test(): mes = "god" print(mes) print_test() # print(mes) 無法從外部呼叫

不行設定成可變物件

mutable object

課後作業:什麼是 mutable?

必須指向不可變對象

預設值盡量不要用空串列或字典

def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print(f(3)) # 輸出 [1] [1, 2] [1, 2, 3]

需改成

def f(a, L=None): if L is None: L = [] L.append(a) return L print(f(1)) print(f(2)) print(f(3)) # [1] # [2] # [3]

全域引數

mes = "god" def print_test(): global mes mes = "變更參數" print(mes) print_test() print(f"再次查看:{mes}") 變更參數 再次查看:變更參數

有內定鍵值的引數

有內定值的引數要放在後面

https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments

  • 位置對應引數 postion arguments
  • 關鍵字對應引數 keyword(s) arguments

沒講清楚,預設對位置
混合使用,需要先對位置再用 keyword

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'): print("-- This parrot wouldn't", action, end=' ') print("if you put", voltage, "volts through it.") print("-- Lovely plumage, the", type) print("-- It's", state, "!") # parrot("123", state=1000)

不固定數量引數

查找語法手冊看到:

breakpoint(*args,**kws)

可變引數(*args 和 **kwargs)

(有先後順序,先一顆星,再來兩顆星)

  • 一顆星 包住 元組 (a,b)
  • 兩顆星 包住 字典 {key:value}

(感覺很高手的做法,竟然可以把 key 傳入變成字典)

字典跑迴圈,拿出來的是鍵值 key
可以再用 key 取值,dic[key]

  • 提醒 key 只能是字串,元素,元組
def func(a,*t, **d): for i in range(a): print("*") print(t) print(d) for key in d: print(key,d[key]) func(4,"abc","def","ghi",k=1,m=2) # * # * # * # * # ('abc', 'def', 'ghi') # {'k': 1, 'm': 2} # k 1 # m 2
def cheeseshop(kind, *arguments, **keywords): print("-- Do you have any", kind, "?") print("-- I'm sorry, we're all out of", kind) for arg in arguments: print(arg) print("-" * 40) for kw in keywords: print(kw, ":", keywords[kw])
def add_all(*add): result = 0 for i in range(len(add)): result += add[i] return result print(add_all(1, 2, 3, 4, 5)) # 15

特殊參數 Special parameters

https://docs.python.org/3/tutorial/controlflow.html#special-parameters

範例:

def func(pos1, pos2, /, pos_or_kwd, *, kwd_only):
    print(pos1, pos2, pos_or_kwd, kwd_only)

func(1, 2, 3, kwd_only=4)  # 正確
func(1, 2, pos_or_kwd=3, kwd_only=4)  # 正確
# func(1, 2, 3, 4)  # 錯誤:kwd_only 只能作為關鍵字參數

Argument 跟 Parameters 翻譯差異推論

  • Parameter(參數):函數定義時列出的變數名稱,用來函數呼叫時提供的值。 def func(a, b=5):ab 是參數。

  • Argument(引數):函數被呼叫時實際傳入函數的值。func(10, 20) 中,1020 是傳入的引數。


我的練習推論:

e.g : `discord.py` 模組

ctx ---> 作為引數 argument,傳遞上下文

模組底下可以用的方法 run 可以帶入的參數 Parameter
https://discordpy.readthedocs.io/en/stable/api.html?highlight=get%20channel#discord.Client.get_channel

三個區域的參數規則
(第一個 / 第二個區域 *,_第三個)

pos only / pos or keyword *, keyword only

例如 BIF函式

max(iterable, *, key = None)

print(*objects, sep=' ', end='\n', file=None, flush=False)

print(1,2,3) # 123都給object 星號代表全收
那要怎麼設定後面的參數
print(1,2,3,sep="#")
sort(對位置/,*,key=None)

Unpacking

解包,用更精簡的表達方式取出資料

args = [3, 6]
list(range(*args))   

range() function

https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists

https://zhuyinjun.me/2019/python_unpacking_and_packing_1/

https://www.learncodewithmike.com/2019/12/python-unpacking.html

課後作業:什麼是 packing unpacking?
課後作業:什麼是 mutable inmutable?

留作自學,課堂並未教學

Documentation Strings

Pycharm 會提示你怎麼使用,就是使用 doc-strings

def func(x): """ :param x: it means.... :return: """ match x: case "最小的": return 5 case 2: return 4 case 3: return 3 case 4: return 2 case "最大的": return 1 max(["最小的",2,3,4,"最大的"], key=func) # 年紀最小的

例外處理

錯誤類型

分成兩大類: 語法錯誤 與 邏輯錯誤

tryexcept 是處理邏輯錯誤

for 迴圈正常結束後 else 才會繼續做

if 不成立後才執行 else

try無錯誤才執行 else

Python Errors and Exceptions:
https://docs.python.org/3/tutorial/errors.html

Python 所有錯誤資訊:
https://docs.python.org/3/library/exceptions.html#exception-hierarchy

Python 例外處理教學文章:
https://steam.oxxostudio.tw/category/python/basic/try-except.html

https://ithelp.ithome.com.tw/articles/10262492

錯誤訊息:

截圖 2024-08-16 上午10.27.33

常見錯誤類型

錯誤資訊 說明
NameError 使用沒有被定義的對象
IndexError 索引值超過了序列的大小
TypeError 數據類型 ( type ) 錯誤
SyntaxError Python 語法規則錯誤
ValueError 傳入值錯誤

TryExcept

a = "1"

try:
    a += 1
    print(a)
except TypeError:
    print('型別發生錯誤')
except NameError:
    print('使用沒有被定義的對象')
print('hello')

def func(a,b):
    try:
        c = a/b
        # return c
    except ZeroDivisionError:
        print("Division by zero")
    except Exception as e:
        print("包山包海",e)
    else:
        print("else:")
        return c
    finally:
        print("會執行")

Raise

自我拋出錯誤

def func(num):
    try:
        # 要進行錯誤捕捉的程式碼
        x = int(input("輸入小於十的正整數: "))
        num += x
        # x += a # 錯誤測試
        if x > 10 or x < 0:
            raise ValueError("您輸入的數字必須小於十的正整數") #主動拋出錯誤
    except NameError as e:
        print("使用沒有被定義的參數 !", e)
    except TypeError as e:
        print("參數資料類型格式錯誤 !", e)
    except ValueError as e:
        print("資料傳入錯誤", e)
    except KeyboardInterrupt as e:
        print("程式被用戶中斷", e)
    except EOFError as e:
        print("未預期的結束輸入", e)
    except Exception as e:
        print("總之就是錯了", e)
    else:
        # 沒有錯誤,就會執行這裡
        print(num)
    finally:
        # 不管有沒有錯誤都會執行這裡
        print("一定執行")


Pass

不做任何動作略過

(非 return)

Assert

assert False, "錯誤訊息"

Finally

程式註解文字引用來源:
https://chwang12341.medium.com/給自己的python小筆記-debug與測試好幫手-嘗試try-except與主動引發raise與assert-程式異常處理-de0099d32bbe

try: 要進行錯誤捕捉的程式碼 except 錯誤類型a as e: ##e 是用來記住錯誤資訊,可以不寫 如果程式發生錯誤類型為a,就會執行這裡 except 錯誤類型b: 如果錯誤類型為b,就會執行這裡 except (錯誤類型c, 錯誤類型d) as f: ## 用來同時捕捉多個錯誤 如果錯誤類型符合錯誤類型c與錯誤類型d,就會執行這邊 except Exception as e: 如果不知道會發生的錯誤類型為何,可以使用它,除了你寫下要捕捉的錯誤類型,其餘發生的錯誤都會執行這裡 else: 如果沒有錯誤,就會執行這裡 finally: 不管有沒有錯誤都會執行這裡

冷知識:當參數設定為 "e" 時

https://youtube.com/shorts/Yo6KSHdImkQ?si=W1nnkXYYXPcp2Tuo

單元測試框架

unittest

https://docs.python.org/zh-tw/3/library/unittest.html

( 高階使用者使用,日後學習,for 考試先記住規則 )

截圖 2024-08-19 上午11.14.48

類別 大寫字母開頭(繼承類別):

​​​​def 方法:
​​​​def 方法:

self.assertIsInstance(obj, cls, msg=None)

Return

return 返回一個( 任何物件 )
可以是字串,可以是串列,可以是陣列

發現到特別之處,finally 會在 return 前執行。


def count(a):
    try:
        a += 1
    except Exception as e:
        print("發生異常:", e)
    else:
        return a
    finally:
        print("最後執行")

print(count(1))


else 只能接在 except 之後

finally 會在 return 前執行,finally 若有 return 會覆蓋前面的 return

官方手冊案例:只使用 try 跟 finally
(沒有人會這樣寫吧)

(考題若出答案選錯誤,try 一定要配 except)
https://docs.python.org/3/tutorial/errors.html#defining-clean-up-actions