lucasw
大佬教麻
從入門到入土
Full Stack
Discord Bot
Machine Learning
Unity
Competitive Programming
Web Crawler
Server Deployment
Minecraft Datapack
Scratch
What is Python?
Hello World!
Variable
Data Structure
Loop & Decision Making
Function
Object Oriented Programming
Modules
Error Handler
Example
是蟒蛇嗎?能吃嗎?
能讓人透過指令與電腦溝通的語言
像是C、C++、Python、Java等等
其中程式語言也可以分成許多種類,常見的分類如下
在執行時將程式透過直譯器一句一句的同時轉換成機器碼並且執行
優點是不用預先編譯,比較方便快速
例:Javascript、PHP、Ruby
先透過編譯器將程式編譯成機器碼,在執行時執行編譯後的檔案
優點是通常程式執行速度通常較直譯語言快
例:C、C++、Rust
Python的位元組碼會被放在名為__pycache__的資料夾內
副檔名為.pyc
型別可以混用,不需要在變數宣告時固定
優點是對於一個變數可以用來儲存不同類型的資料
例:Javascript、PHP、Ruby、Python
型別不能混用,要在宣告時就指定好型別
優點是程式可以在編譯期時抓到錯誤,而且使用者可以清楚知道這個變數的類型
例:C、C++、Rust
對於初學者來說,動態型別可以讓你比較好寫,但是到了後期普遍會建議靜態型別,能夠避免一些因為型別而產生的bug
像是Python後來也開始重視這件事,因此從Python3.5開始有了新的型別標記語法來讓型別可以在編譯期知道
圖中可以看到a在宣告時沒有說明型別
因此編譯器判斷它有可能是str
而b已經宣告為int,底下若是str才會發生的程式碼被自動暗化了
對於初學者來說,動態型別可以讓你比較好寫,但是到了後期普遍會建議靜態型別,能夠避免一些因為型別而產生的bug
像是Python後來也開始重視這件事,因此衍生了新的型別標記語法來讓型別可以在編譯期知道
不同型別之間不能進行運算
優點是不會發生不該進行運算時運算
例:Python、Java、Ruby
在兩個不同型別計算時會幫你偷偷轉換,讓他可以被運算
優點是不用多一次轉換型別也能直接丟進去運算
例:C、C++、Javascript
在強型別中能看到他不會讓你執行
而弱型別雖然執行了但是結果可能與想像中的不一樣
(C++會將字元轉換成ASCII碼)
你好 世界!
根據你的作業系統下載指定版本
之後點開下載下來的安裝程式
這個選項記得勾起來
(預設是不勾)
若是沒有新增Python到%PATH%環境變數
之後IDE與終端可能會抓不到你的Python編譯器
整合開發環境
顯然我們寫程式不會用記事本寫
我們通常會使用IDE去編寫程式
而這次的課程將會使用泛用性高同時支援各種
語言與插件的Visual Studio Code
與Python一樣找到對應版本下載
之後執行安裝程式
這次就不用新增什麼環境變數了
一路下一步到底
有些快捷鍵可以記一下
F2 重新命名
F5 執行程式並偵錯
Ctrl + Z 還原上一步
Ctrl + Y 還原還原上一步
Ctrl + N 新增檔案
Ctrl + S 儲存檔案
Ctrl + F 查詢指定字串
Ctrl +Shift + L 同時選取所有指定字串
Ctrl +Shift + P 選取VSCode指令
要在VSCode寫Python
當然要先裝Python的插件
如果跟我一樣英文苦手的就裝吧
至少看一堆專有名詞不用去通靈
可以在背景放上你想放的任何圖片
聽起來不香嗎
如果之後有打算寫更多東東
裡面或許有些功能是你會用到的
創建一個新的檔案
命名附檔名要是.py
print("hello world!")
在檔案內容輸入以下文字
之後敲下你的F5或是點右上角的執行
如此一來你就能在底下看到你的運行結果了
恭喜你! 踏出了所有工程師的第一步了!
變數
假設我們今天有一筆資料A
把他存放在一個地方
假設我們今天有一筆資料A
把他存放在一個地方
而這個存放他的箱子
就成為變數
你可以隨時放入其他東西進入箱子
也可以隨時檢查箱子裡的東西
你可以隨時放入其他東西進入箱子
也可以隨時檢查箱子裡的東西
而此時存放在箱子裡的物品種類
我們稱為資料型態
Python的資料型態我們先簡單講解
以下幾種
int | 整數類型(包含正負數) |
---|---|
float | 浮點數類型(包含正負數) |
str | 字串類型 |
bool | 布林值類型(True、False) |
a = 1 # 往一個叫做a的箱子放入一個內容為1的整數
print(a) # 把a打印出來
b = 1145141919810 # 往一個叫做b的箱子放入一個內容為1145141919810的整數
print(b) # 把b打印出來
可以看到存放的整數數字被成功地打印出來了
當然你也可以對數字做各種運算
+ | 加法 |
---|---|
- | 減法 |
* | 乘法 |
/ | 除法 |
% | 取餘數 |
** | 次方 |
當然你也可以對數字做各種運算
a = 1 + 1 #直接對數字進行運算
b = 1 - 2
print(a)
print(b)
c = a * b # 對變數也可以進行運算
print(c)
Python的話沒有數字大小的上限
但是要注意數字如果真的太大你的電腦可能會無法負荷
浮點數就是小數
與整數一樣可以做各種運算
pi = 3.14
r = 5
print(r * r * 3.14)
字串需用英文的引號包起來("str" or 'str')
而且想不到吧 字串可以做各種運算
a = "ian"
b = "gay"
print(a + " is " + b * 5)
字串可與字串相加
且可乘上一個整數使字串重複
a = "ian"
b = "gay"
print(a + " is " + b * 5)
可以使用f-string讓變數插入在字串內
f"{變數名}"
name = "小明"
gender = "男"
age = 18
score = 90
print(f"有個{age}歲的{gender}學生叫做{name},他考了{score}分")
布林值只有True跟False兩種可能
可以在之後的 if 陳述式用到
如果拿去做運算會將
True視為1,False視為0
lucas_is_dian = False
izcc_is_dian = True
print(lucas_is_dian)
print(izcc_is_dian)
布林值的產生也可能是從比較運算符
> | 大於 |
< | 小於 |
== | 等於(注意要兩個=) |
>= | 大於等於 |
<= | 小於等於 |
!= | 不等於 |
布林值的產生也可能是從比較運算符
a = 1000 > 2000
b = "haha" == "haha"
print(a)
print(b)
資料結構
剛剛提到變數就像是一個盒子
可以存放單個資料進去
但是如果我想要一個不一樣功能的容器
像是櫃子、抽屜等等的呢?
這些存放資料的容器
稱之為資料結構
簡單介紹以下幾種Python的資料結構
tuple | 數組,可以放一堆東西進去 |
---|---|
list | 串列,可以放一堆東西進去 |
set | 集合,可以放不重複的東西進去 |
dict | 字典,一個key對應一個value |
※ 資料結構亦屬於資料型態的一種
數組以括號( )包住
裡面可以放入各種資料型態
就像是一個櫃子一樣
每一層可以放入不同東西
可以對數組使用[index]去得到指定索引存放的數值
在程式中通常index(索引)以0為起點
所以一個 數組a / 陣列a 的第一個元素
會以a[0]表達
0
1
櫃子[0] = 香蕉
櫃子[1] = 魚
我們創建一個名為ckefgisc的數組
放進去兩個字串
之後打印第0項與第1項
ckefgisc = ("建中電研", "北一資訊")
print(ckefgisc[0])
print(ckefgisc[1])
另外數組可以使用以下兩種方法
students = ("Lucas", "Ian", "Shawn", "Shawn")
print(students.count("Shawn"))
print(students.index("Shawn"))
count(x): 回傳x在數組中的數量
index(x): 回傳數組中第一個x的索引
ckefgisc = ["建中電研", "北一資訊"]
print(ckefgisc[0])
print(ckefgisc[1])
students = ("Lucas", "Ian", "Shawn", "Shawn")
print(students.count("Shawn"))
print(students.index("Shawn"))
串列以中括號[ ]包住
你可以對它進行與數組一樣的操作
pokemon = ["妙蛙種子", "小火龍", "傑尼龜"]
pokemon.append("皮卡丘")
print(pokemon)
pokemon.insert(1, "綠毛蟲")
print(pokemon)
pokemon.remove("綠毛蟲")
print(pokemon)
pokemon.pop(1)
print(pokemon)
pokemon.reverse()
print(pokemon)
在串列之中,你還可以對它做各種插入反轉等等的操作
pokemon = ["妙蛙種子", "小火龍", "傑尼龜"]
pokemon.append("皮卡丘")
print(pokemon)
# >>['妙蛙種子', '小火龍', '傑尼龜', '皮卡丘']
pokemon.insert(1, "綠毛蟲")
print(pokemon)
# >>['妙蛙種子', '綠毛蟲', '小火龍', '傑尼龜', '皮卡丘']
pokemon.remove("綠毛蟲")
print(pokemon)
# >>['妙蛙種子', '小火龍', '傑尼龜', '皮卡丘']
pokemon.pop(1)
print(pokemon)
# >>['妙蛙種子', '傑尼龜', '皮卡丘']
pokemon.reverse()
print(pokemon)
# >>['皮卡丘', '傑尼龜', '妙蛙種子']
其他更多操作礙於篇幅問題講不完
其他更多操作礙於篇幅問題講不完
好奇的話可以去看
集合以大括號{ }包住
其中每個元素不能重複
並且你可以對它進行各種數學上的集合運算
a = {10, 20, 30, 40}
b = {30, 40, 50, 60}
print(a & b) # {40, 30}
print(a | b) # {40, 10, 50, 20, 60, 30}
print(a - b) # {10, 20}
print(b - a) # {50, 60}
print(a ^ b) # {10, 50, 20, 60}
字典以大括號{ }包住
裡面每個元素為一個key對應一個value
寫法為{key: value}
eng_to_tw = {"ckeisc": "建中電研", "fgisc": "北一資訊"}
print(eng_to_tw["ckeisc"]) # 建中電研
print(eng_to_tw["fgisc"]) # 北一資訊
print(eng_to_tw["建中電研"]) # KeyError: "建中電研"
使用 字典[key] 可以獲得 value
但是兩者不能反過來用
eng_to_tw = {"ckeisc": "建中電研", "fgisc": "北一資訊"}
print(eng_to_tw["ckeisc"]) # 建中電研
print(eng_to_tw["fgisc"]) # 北一資訊
print(eng_to_tw["建中電研"]) # KeyError: "建中電研"
當然你也可以混用各種資料結構
像是這樣
school = [
{
"name": "CKHS",
"club": [
("電研", "CKEISC"),
("資訊", "CKINFOR")
]
},
{
"name": "TFG",
"club": [
("資訊", "FGISC")
]
},
]
print(school[0]["club"][0][0]) # 電研
print(school[0]["club"][0][1]) # CKEISC
print(school[0]["club"][1][0]) # 資訊
print(school[0]["club"][1][1]) # CKINFOR
print(school[1]["club"][0][0]) # 資訊
print(school[1]["club"][0][1]) # FGISC
迴圈 & 抉擇
如果我今天想要打印5個hello world
這時候該怎麼做呢?
print("hello world")
print("hello world")
print("hello world")
print("hello world")
print("hello world")
不是不行
但看起來有點亂
而我今天想要打印50000個hello world
這時候該怎麼做呢?
print("hello world")
print("hello world")
print("hello world")
print("hello world")
print("hello world")
...
不可能吧
這個時候可以使用for語法來指定重複次數
for i in range(50000):
print("hello world")
這樣是不是簡單多了呢
for i in range(50000):
print("hello world")
解釋一下
range(x)函式會產生一個0~(x-1)的迭代器
對我知道很難理解
你可以想像成它會產生這樣的東西
range(5) => [0, 1, 2, 3, 4]
解釋一下
range(x)函式會產生一個0~(x-1)的迭代器
對我知道很難理解
你可以想像成它會產生這樣的東西
range(5) => [0, 1, 2, 3, 4]
而for會讓後面的變數依序變成陣列內的每一個數字
for i in [1, 3, 5, 7, 9]:
print(i)
而迴圈還有另一種
那就是while迴圈
它會在滿足指定條件時不斷的執行
a = [10, 20, 30, 40, 50]
while len(a) > 0: # 當a陣列的元素數量大於0時
print(a.pop()) # 移除a陣列的最後一個元素並印出
是不是很簡單呢
a = [10, 20, 30, 40, 50]
while len(a) > 0: # 當a陣列的元素數量大於0時
print(a.pop()) # 移除a陣列的最後一個元素並印出
如果...那麼...
在滿足條件時才執行裡面的程式碼
直接上範例
lucas_is_dian = False
izcc_is_dian = True
if lucas_is_dian:
print("lucas orz....")
if not lucas_is_dian:
print("lucas is not dian....")
if izcc_is_dian:
print("izcc orz....")
if not izcc_is_dian:
print("izcc is not dian....")
lucas_is_dian = False
izcc_is_dian = True
if lucas_is_dian:
print("lucas orz....")
if not lucas_is_dian:
print("lucas is not dian....")
if izcc_is_dian:
print("izcc orz....")
if not izcc_is_dian:
print("izcc is not dian....")
else則是在不滿足if的時候會被調用
z = 10
b = 20
if z > b:
print("good")
else:
print("bad")
而如果有更多選項可以使用elif
(elif = else if)
score = 59
if score == 100: print("A++")
elif score >= 95: print("A+")
elif score >= 90: print("A")
elif score >= 85: print("B++")
elif score >= 80: print("B+")
elif score >= 70: print("B")
elif score >= 60: print("C")
else: print("中華民國國軍是一個積極新創、人才齊全、戰鬥兵力雄厚、訓練特色鮮明的部隊,在國際上具有重要影響力與競爭力,在多個領域具有非常前瞻的科技實力,擁有世界一流的武器裝備與師資力量,各種排名均位於全球前列,並且擁有公開透明的升遷管道、各種進修資源,以及婚喪生育補助可以申請,歡迎大家報考志願役。\n國軍人才招募專線:0800-000-050")
當你的判斷都是
elif x=="A"
elif x=="B"
那可以換成使用match-case
會讓你的效能與可讀性都更高
grade = "F"
match grade:
case "A": print("Average")
case "B": print("Below Average")
case "C": print("Can't have dinner")
case "D": print("Don't come home")
case "F": print("Find a new family")
函式
當一個功能的程式可以被用在許多地方
這時候就可以把它包成一個函式
在需要的時候呼叫它
def helloworld():
print("Hello World!")
helloworld() # Hello World!
函式可以有回傳值
以return表示
此時會將函式視為回傳值後續處理
def helloworld():
return "Hello World!"
print(helloworld()) # Hello World!
如果說這個函式每次使用的時候都會
有一些數值是不一樣的
這時候可以設定函式的參數
def add(a, b):
return a + b
print(add(1, 2)) # 3
我們可以使用型別標記來告訴使用者
這個函式的參數、回傳值是什麼類型
def add(a: int, b: int) -> int:
return a + b
print(add(1, 2)) # 3
你也可以設定每個參數的預設值
def add(a: int=10, b: int=20) -> int:
return a + b
print(add()) # 30
print(add(1)) # 21
print(add(1, 2)) # 3
而一般的參數可以有兩種放入方式
add(1, 2)
按照參數順序放入 (位置參數)
add(a=1, b=2)
把值給到指定參數 (關鍵字參數)
我們可以使用星號 * 來強制使用者只能用關鍵字參數
def student(name: str, age: int, score: float, gender: str) -> str:
return f"有個{age}歲的{gender}學生叫做{name},他考了{score}分"
print(student("小明", 18, 90, "男"))
# >>有個18歲的男學生叫做小明,他考了90分
def student(*, name: str, age: int, score: float, gender: str) -> str:
return f"有個{age}歲的{gender}學生叫做{name},他考了{score}分"
print(student("小明", 18, 90, "男"))
# >>TypeError: student() takes 0 positional arguments but 4 were given
print(student(name="小明", age=18, score=90, gender="男"))
# >>有個18歲的男學生叫做小明,他考了90分
星號打在哪裡就代表在星號之後的參數
一律只能使用關鍵字參數
def student(name: str, age: int, *, score: float, gender: str) -> str:
return f"有個{age}歲的{gender}學生叫做{name},他考了{score}分"
print(student("小明", 18, score=90, gender="男"))
# >>有個18歲的男學生叫做小明,他考了90分
範例內name、age可以用位置參數 / 關鍵字參數
但是score、gender只能使用關鍵字參數
物件導向程式設計
在進行有別於一般小程式的大專案時
理想情況會希望專案能夠像是一台機器人
每個部件分開來去製作
最後再合起來成為機器人
這樣一旦某個部件出問題只要維修該部件
不會一行程式出了問題就要對整個程式地毯式debug
假設我們要來寫一個
實際經驗應該比較有說服力ㄅ
假設我們要來寫一個
實際經驗應該比較有說服力ㄅ
我們可能會先建立一個站點的物件
class Station:
name: str
lines: list[str]
id: int
def get_infor(self) -> str:
return f"{self.name}({self.lines})"
station = Station()
station.name = "中正紀念堂"
station.lines = ["紅線", "綠線"]
print(station.get_infor())
# >>中正紀念堂(['紅線', '綠線'])
class後面接名稱
物件內可以放入函式或是變數
使用 station.name 獲得station物件內的name屬性
我們可以想像每個class都是張藍圖
經過實例化後可以指定一個物件使用這張藍圖
class Station:
name: str
lines: list[str]
id: int
def get_infor(self) -> str:
return f"{self.name}({self.lines})"
station = Station()
station.name = "中正紀念堂"
station.lines = ["紅線", "綠線"]
print(station.get_infor())
# >>中正紀念堂(['紅線', '綠線'])
只要這個class經過實例化(第8行)
class的函式第一個傳入的參數會是物件本身
我們一般習慣命名叫做self
class Station:
name: str
lines: list[str]
id: int
def get_infor(self) -> str:
return f"{self.name}({self.lines})"
station = Station()
station.name = "中正紀念堂"
station.lines = ["紅線", "綠線"]
print(station.get_infor())
# >>中正紀念堂(['紅線', '綠線'])
在實例化時會用a = class()
出現了括號() 聰明的你可能已經想到了
這邊可以使用__init__來當作實例化時呼叫的函式
class Station:
def __init__(self, name: str, lines: list[str], id: int) -> None:
self.name = name
self.lines = lines
self.id = id
def get_infor(self) -> str:
return f"{self.name}({self.lines})"
station = Station("中正紀念堂", ["紅線", "綠線"], 1)
print(station.get_infor())
# >>中正紀念堂(['紅線', '綠線'])
我們有了站點的物件了
接著要來創建捷運圖的物件
class Metro:
def __init__(self) -> None:
self.stations: list[Station] = []
def add_station(self, name: str, lines: list[str], id: int) -> None:
self.stations.append(Station(name, lines, id))
def remove_station(self, id: int) -> None:
for station in self.stations:
if station.id == id:
self.stations.remove(station)
break
def get_station(self, id: int) -> Station | None:
for station in self.stations:
if station.id == id:
return station
return None
如此一來就完成了一個可以控制的站點管理系統了
class Metro:
def __init__(self) -> None:
self.stations: list[Station] = []
def add_station(self, name: str, lines: list[str], id: int) -> None:
self.stations.append(Station(name, lines, id))
def remove_station(self, id: int) -> None:
for station in self.stations:
if station.id == id:
self.stations.remove(station)
break
def get_station(self, id: int) -> Station | None:
for station in self.stations:
if station.id == id:
return station
return None
不過現在有個小問題
我們不希望使用者可以直接調用self.stations來獲得資訊
class Metro:
def __init__(self) -> None:
self.stations: list[Station] = []
def add_station(self, name: str, lines: list[str], id: int) -> None:
self.stations.append(Station(name, lines, id))
def remove_station(self, id: int) -> None:
for station in self.stations:
if station.id == id:
self.stations.remove(station)
break
def get_station(self, id: int) -> Station | None:
for station in self.stations:
if station.id == id:
return station
return None
Python有別於其他的物件導向語言
有著private的屬性
但是可以透過命名規則來做到相同的功能
單底線開頭:告訴工程師不要用,沒有強制力
雙底線開頭:你想用也沒辦法使用
另外不要雙底線開頭 + 雙底線結尾,那是Python特殊功能函數
如 __init__()
這麼一來就可以告訴別人不要直接調用了
※一般通常不會直接用雙底線寫死
class Metro:
def __init__(self) -> None:
self._stations: list[Station] = []
def add_station(self, name: str, lines: list[str], id: int) -> None:
self._stations.append(Station(name, lines, id))
def remove_station(self, id: int) -> None:
for station in self._stations:
if station.id == id:
self._stations.remove(station)
break
def get_station(self, id: int) -> Station | None:
for station in self._stations:
if station.id == id:
return station
return None
那如果我們想再創建一個有更多功能的捷運系統
但是也想保留舊的系統
那該怎麼寫呢
class ExtraMetro(Metro):
def __init__(self, lines: list[str]) -> None:
self._lines = lines
super().__init__()
def find_stations_on_line(self, line: str) -> list[Station] | None:
if line not in self._lines:
return None
output = []
for station in self._stations:
if line in station.lines:
output.append(station)
return output
這個時候就要用到 繼承
語法為在class的名稱後面加上(要繼承的class)
classA(classB)
此時classA可以擁有所有classB的屬性
_stations / add_station / remove_station / get_station
class ExtraMetro(Metro):
def __init__(self, lines: list[str]) -> None:
self._lines = lines
super().__init__()
def find_stations_on_line(self, line: str) -> list[Station] | None:
if line not in self._lines:
return None
output = []
for station in self._stations:
if line in station.lines:
output.append(station)
return output
這時候可能有人發現了
這裡使用到一個神奇的函式super()
他相當於被繼承的classB
而這行便是執行classB的__init__函式
讓self._stations能夠被建立
到這邊物件導向的基礎就差不多結束了
實際上還有更多的相關語法
如更多的Python內建函式、多重繼承、不實例化的用法等等
如果感興趣的可以去閱讀官方文檔
模組
如果A寫了一個檔案包含了各種演算法模板
而B今天想要使用這個檔案的內容到自己的程式 (main.py)
這時候該怎麼做呢?
# DFS.py
visited = [False] * 1000
def dfs(graph: list[list[int]], cur: int=1, deep: int=1) -> int:
if visited[cur]:
return deep
visited[cur] = True
deeps = [deep]
for i in graph[cur]:
deeps.append(dfs(graph, i, deep + 1))
return max(deeps)
# DFS.py
visited = [False] * 1000
def dfs(graph: list[list[int]], cur: int=1, deep: int=1) -> int:
if visited[cur]:
return deep
visited[cur] = True
deeps = [deep]
for i in graph[cur]:
deeps.append(dfs(graph, i, deep + 1))
return max(deeps)
import DFS # 匯入DFS.py
graph = [[], [2, 3], [4, 5], [6, 7], [], [], [], []]
print(DFS.dfs(graph)) # 使用DFS底下的dfs函數
B可以這樣做
import DFS # 匯入DFS.py
graph = [[], [2, 3], [4, 5], [6, 7], [], [], [], []]
print(DFS.dfs(graph)) # 使用DFS底下的dfs函數
B也可以這樣做
from DFS import dfs # 匯入DFS.py的dfs函數
graph = [[], [2, 3], [4, 5], [6, 7], [], [], [], []]
print(dfs(graph)) # 直接使用dfs函數
而這就是函式庫的基本運行
當然你會發現程式把DFS.py當成了一個物件一般
可以獲取底下的函式 / 其他物件
在Import語法中所有的檔案跟資料夾
會變成一個物件的層級關係
舉個🌰
這是我們目前的資料夾架構
在a.py中有StudentA物件
在b.py中有StudentB物件
from school_1.a import StudentA
from school_2.b import StudentB
a = StudentA("Alice", 18)
b = StudentB("Bob", 19)
...
此時可以這樣引用
如果我們增加一個print_b.py
目標是調用b.py的物件
from ..school_2.b import StudentB
那麼可以這樣引用
. 放在開頭可以用來表示上層資料夾
而你甚至可以直接引用一個資料夾
只需要為它添上一個
__init__.py (這個是python固定的檔案名稱)
# __init__.py
a = "Hello World"
# main.py
import folder
print(folder.a) # Hello World
此時Python會將__init__.py
當作folder資料夾的預設內容
當你引用folder 實際上就是在引用__init__.py
最後注意一下
所有引用自上級資料夾檔案的方式
均需要目前環境在這個資料夾下
若是引用了超越目前所在目錄層級的資料夾
Python 將會在引用時報錯
錯誤處理
你是否有時候會在程式執行時
跑出這些東西
KeyError
NameError
TypeError
你是否有時候會在程式執行時
跑出這些東西
這些東西其實是有方法去偵測
甚至是自定義的
KeyError
NameError
TypeError
讓我們舉個例子
a = {}
print(a["empty"])
這很明顯我們在抓取一個不存在的key
但是如果我想要讓他在觸發KeyError時
順便把a[key]設為key呢?
try會執行它裡面的程式
但是一旦遇到指定的錯誤就會掉轉到except的地方去做執行
class A:
a_dict = {}
def __getitem__(self, key):
try:
output = self.a_dict[key]
except KeyError:
output = key
return output
a = A()
print(a["empty"])
class A:
a_dict = {}
def __getitem__(self, key):
try:
output = self.a_dict[key]
except KeyError:
output = key
return output
a = A()
print(a["empty"])
如此一來
便能達到觸發錯誤就進行某件事的功能了
剛剛的例子其實可以換成偵測key是否存在去排除抓空的可能
但是下面這個例子就只能使用try去偵測
try:
for i in range(10000000):
print(i)
except KeyboardInterrupt:
print("bye bye....")
程式會不斷打印數字
直到使用者使用Ctrl + C強制中斷程式
而KeyboardInterrupt會在程式被Ctrl + C時觸發
此時程式就會和你說byebye啦
而try還有一個功能
那就是finally
這個指令會在try或是except的程式執行完畢後執行
try:
print(1/0)
except ZeroDivisionError:
print("You can't divide by zero....")
finally:
print("calculation is done....")
而try還有一個功能
那就是finally
這個指令會在try或是except的程式執行完畢後執行
此功能通常被應用在連線時或是開啟檔案時
可以確保不論是否引發錯誤最後都會關閉連線 / 檔案
講了發生錯誤後能怎麼偵測
那如果你想要引發怪怪的錯誤呢 (?
students = ["a", "b", "c"]
if "d" not in students:
raise ValueError("d is not in the list")
raise可以引發指定錯誤
可以在錯誤物件的後面加上錯誤訊息
當然你也可以自訂一個錯誤類別並引發它
class TooGayError(Exception):
def __init__(self):
super().__init__("why you so gay")
ckinfor = "gay"
ckcsc = "gay"
if ckcsc + ckinfor == "gaygay":
raise TooGayError
想知道在Python有哪些錯誤類型嗎
可以在適當的時候引發指定錯誤
又或是排除指定錯誤
對開發應用會有很大的幫助
範例
本次課程的所有範例檔案都在裡面
請自行取用
另外如果好奇更多Python的應用可以參考
最後補充一下
Python的成果發表當然就是Python
只要任何使用Python語言寫的程式都可以作為你成發時的作品
你可以使用更多的函式庫去完成你的作品
如果沒有想法的可以去問問ChatGPT
期待成發當天可以看到各位電神們的作品
By lucasw
從零開始教你Python