當發生錯誤或異常時,Python通常會終止執行並產生錯誤訊息。為避免程式意外的終止執行,這些異常可以使用 try..except機制來處理:
# 因 xx 變數未定義,將生成異常
# 觸發 except:區塊的程式執行
try:
print(xx)
except:
print("異常")
# xx變數尚未定義,
# 將生成一個 NameError異常
try:
pxrint(xx)
except NameError:
print("NameError異常:變數未定義")
except:
print("其他異常")
try:
print("Hello")
except:
print("異常")
else:
print("無異常")
finally:
print("finally一定會執行 ")
Python 可以選擇在某些條件發生時,使用 raise 關鍵字拋出異常訊息,並透過 sys 模組的 exc_info()來取得異常訊息:
import sys
def 圓面積(半徑):
# 當半徑為負值,丟出自訂異常
if 半徑 < 0:
raise Exception("半徑不可為負")
else:
return 3.14*半徑**2
try:
圓面積(-1)
except:
# 顯示異常訊息
print(sys.exc_info()[1])
在抽籤程式中,若輸入非數值或起始/結束值,將會造成程式執行錯誤,因此透過異常處理機制來避免程式意外停止執行:
import random
while True:
try:
人數 = int(input("請輸入抽獎人數:"))
起始 = int(input("請輸入起始位置:"))
結束 = int(input("請輸入結束位置:"))
except:
print("請輸入正確的整數")
else:
if 人數 < 0 or 起始 > 結束:
print("人數必須為正數,起始值要小於結束值")
continue
break
候選清單=list(range(起始, 結束+1))
print("獲獎名單為:")
for i in range(人數):
# 隨機抽籤
中籤者=random.choice(候選清單)
print(中籤者)
# 移除已中籤者
候選清單.remove(中籤者)
以上的範例還是有可能因異常造成程式意外停止,請你再進一步改良,避免任何的意外停止執行!
Python主要透過 open()
功能來處理檔案的管理,open()
函數帶有兩個參數:檔名和模式
開啓檔案有四種不同的模式:
另外可以指定文件應以二進制還是文字模式處理
f = open("檔名") 或 f = open("檔名", "rt")
f = open("file/文字檔案.txt", "r")
print(f.read())
f.close()
如果檔案不存在,則會產生錯誤訊息:
f = open("file/不存在的檔案.txt", "r")
print(f.read())
f.close()
----> 1 f = open("file/不存在的檔案.txt", "r") 2 print(f.read()) 3 f.close() FileNotFoundError: [Errno 2] No such file or directory: 'file/不存在的檔案.txt'
# 讀取一行:
f = open("file/文字檔案.txt", "r")
print(f.readline())
f.close()
# 逐行讀取文件:
f = open("file/文字檔案.txt", "r")
for x in f:
print(x, end='')
f.close()
# 寫入檔案
f = open("file/文字檔案.txt", "a")
f.write("\n這是新增的內容")
f.close()
# 讀取檔案
f = open("file/文字檔案.txt", "r")
print(f.read())
f.close()
# 創建新的檔案【執行第二次會出現 File exists 錯誤】
f = open("file/新檔案.txt", "x")
# 寫入一段文字
f.write("這是新檔案的內容")
f.close()
# 讀取檔案
f = open("file/新檔案.txt", "r")
print(f.read())
f.close()
import os
# 刪除檔案
os.remove("file/新檔案.txt")
為避免出現錯誤,在嘗試刪除或建立新檔案之前檢查檔案是否存在:
import os
# 創建新的檔案前先檢查檔案是否存在
if os.path.exists("file/新檔案.txt"):
# 覆蓋寫入舊有的檔案
f = open("file/新檔案.txt", "w")
else:
# 創建新檔案
f = open("file/新檔案.txt", "x")
# 寫入一段文字
f.write("這是新檔案的內容")
f.close()
# 讀取檔案
f = open("file/新檔案.txt", "r")
print(f.read())
f.close()
import os
# 刪除檔案前先檢查檔案是否存在
if os.path.exists("file/新檔案.txt"):
os.remove("file/新檔案.txt")
else:
print("檔案不存在")
類別定義一件事物的抽象特點,包含了屬性(Field)以及對屬性的操作方法(Method)。我們可以將類別想像成汽車的設計藍圖,這張藍圖中會定義屬性(例如車子的顔色、驅動力等規格),另外會定義出車子的功能(方法),例如加速、刹車等。
物件是類別的實例,也就是說有了類別這張藍圖(汽車的設計藍圖),便可以在程式中產生許多同類別的實例(汽車),而這些實例彼此之間是各自獨立的。
類別:設計藍圖,決定汽車要怎麼製造,決定要用什麼規格的輪胎、多少排氣量的引擎、外觀要長怎樣。 物件:實際製造出來的汽車,可以各自獨立去執行不同任務。
物件導向具有三大特性:封裝、繼承、多型
封裝是將物件內部的資料變成是一個黑箱子,只能透過物件所提供的介面(interface)取得內部的屬性或方法,物件設計的細節會被隱藏,其他物件無法也不需要瞭解物件內部的細節,要更動物件內部的資料只能透過物件提供之方法。例如電腦螢幕,我們只需要瞭解其介面的規格,並不需要知道螢幕内部的線路設計,若要更改螢幕的亮度,必須透過螢幕所提供的選單介面更改。
繼承者可以擁有被繼承者的特性。例如:繼承觸控螢幕具有一般螢幕的屬性及方法,也新增了特有的觸控屬性及方法。
Python不支援多載(Overloading)。
簡單來說就是多個相同名稱的方法,透過傳入不同形態的參數,會執行不同的敘述,稱之爲多型。多型(Polymorphism)包含多載(Overloading)和覆蓋(Overriding)。
而多型可以增加程式的彈性,讓相同的函式名稱在執行階段才決定要呼叫那一個函式,進而達「同名異式」的效果。
class myClass:
x = 10
myObj = myClass() #產生實例
print(myObj.x) #列印實例的 x
所有類別都有一個名為 __init __()
的初始化方法,該函數始終在建立物件時自動執行,一般會用在内部屬性的初始值設定,其中第一個參數代表物件本身,一般習慣命名為 self
。
class 學生資料:
def __init__(self, 姓名, 身高, 體重):
self.姓名 = 姓名
self.身高 = 身高/100 #換算爲公尺
self.體重 = 體重
新生1 = 學生資料("王小明", 170, 60)
print(新生1.姓名)
print(新生1.身高)
定義在類別内部的函數稱爲方法,其中第一個參數代表物件本身,一般習慣命名為self
。
class 學生資料:
def __init__(self, 姓名, 身高, 體重):
self.姓名 = 姓名
self.身高 = 身高/100 #換算爲公尺
self.體重 = 體重
def BMI(self):
# BMI=體重/身高的平方
return self.體重/(self.身高**2)
新生1 = 學生資料("王小明", 170, 60)
print(新生1.BMI())
# 修改新生1的體重屬性
新生1.體重=80
print(新生1.BMI())
類別可以定義繼承自另外一個類別的方法和屬性,被繼承的類別稱爲父類別,而繼承下來的類別為子類別。
# 家庭資料繼承自學生資料, 新增家長資料
class 家庭資料(學生資料):
def __init__(self,家長姓名,姓名,身高,體重):
# 呼叫父類別的初始化方法
super().__init__(姓名, 身高, 體重)
# 新增家長資料
self.家長姓名 = 家長姓名
新生1 = 家庭資料("王大明","王小明", 170, 60)
print(新生1.家長姓名)
print(新生1.姓名)
再上述的例子中,類別外部的敘述都可以直接存取類別内部方法和屬性,然而實務上有些方法和屬性不應該被直接存取,應該限制在透過物件所提供的介面來存取,例如下一個例子當中,邊長不應當小於0,但因邊長可以直接被存取,因而無法避免邊長為負值:
class 正方形:
邊長=1.0
def 面積(self):
return self.邊長**2
形狀=正方形()
形狀.邊長=-10; # 邊長為負值
print(形狀.面積())
解決方式便是將半徑設爲私有成員,外部的敘述不能夠直接存取私有成員,只要在成員名稱加上兩個底線即可變成私有成員,直接讀取私有成員會產生錯誤訊息:
class 正方形:
__邊長=1.0
def 面積(self):
return self.__邊長**2
形狀=正方形()
print(形狀.__邊長) #無法讀取
7 形狀=正方形() ----> 8 print(形狀.__邊長) #無法讀取 Attribute Error: '正方形' object has no attribute '__邊長' 屬性錯誤:‘正方形’ 沒有 ‘__邊長’ 屬性
下一個例子當中,因物件不知道私有成員,所以寫入私有成員時,反而會創建新的同名公有屬性
class 正方形:
__邊長=1.0
def 面積(self):
return self.__邊長**2
形狀=正方形()
#會創建新的同名公有屬性
形狀.__邊長=-10;
print(形狀.__邊長)
#面積仍會以私有的 __邊長=1.0 計算
print(形狀.面積())
總而言之,要讀取或寫入私有成員,皆應透過界面方法:
class 正方形:
__邊長=1.0
#取得邊長的界面方法
def 取得邊長(self):
return self.__邊長
形狀=正方形()
print(形狀.取得邊長())
class 正方形:
__邊長=1.0
def 面積(self):
return self.__邊長**2
# 設定邊長的界面方法
def 設定邊長(self, 邊長):
if 邊長 < 0:
print("邊長不可為負")
else:
self.__邊長=邊長
形狀=正方形()
形狀.設定邊長(-10); #設定會失敗
print(形狀.面積())
上例中,雖然會顯示邊長不可為負值!的訊息,但 形狀.面積() 還是會被執行,透過 raise Exception
及try..except
機制可以避免此錯誤:
import sys
class 正方形:
__邊長=1.0
def 面積(self):
return self.__邊長**2
# 設定邊長的界面方法
def 設定邊長(self, 邊長):
if 邊長 < 0:
raise Exception("邊長不可為負")
else:
self.__邊長=邊長
形狀=正方形()
try:
形狀.設定邊長(-10);
print(形狀.面積())
except:
print(sys.exc_info()[1])
套件會包含了一系列的模組,就像是資料夾内包含許多檔案。
第三方套件是需要額外安裝的套件,一般可以透過Python的pip套件管理工具來安裝及管理套件,請依序開啓下列選單,開啓[命令提示字元]視窗 [File]->[Open...]->右上角[new▾]->[Terminal]。 在[命令提示字元]視窗可輸入下列 pip 指令:
例如下列指令會安裝 QR code 套件
pip install qrcode
Microsoft Azure Notebooks 請在code區塊中執行下列指令:
!pip install qrcode
from gtts import gTTS
tts = gTTS("你好,我是谷歌小姐", lang='zh-tw')
tts.save("hello.mp3")
from gtts import gTTS
import playsound
msg = [
"你好,我是谷歌小姐",
"如果有什麼需要我唸的文字",
"請把它放在這裡",
"我會一句一句把它唸出來"
]
i=0;
for m in msg:
print(m)
tts = gTTS(m, lang='zh-tw')
tts.save("{}.mp3".format(i))
playsound.playsound("{}.mp3".format(i))
i+=1
安裝好qrcode套件後,執行下列程式碼,便會產生對應的QR Code:
import qrcode
im=qrcode.make("http://ewin.tw/python")
im.show()
im.save("myqrcode.jpg")
from PIL import Image
# 開啓圖片
im=Image.open("myqrcode.jpg")
# 顯示圖片
im.show()
# 另存圖片
im.save("output.jpg")
旋轉圖片
from PIL import Image
im=Image.open("myqrcode.jpg")
# 圖片旋轉 45度
out=im.rotate(45)
out.show()
out.save("output.jpg")
圖片濾鏡效果
from PIL import Image
from PIL import ImageFilter
im=Image.open("myqrcode.jpg")
# 輪廓濾鏡效果
out=im.filter(ImageFilter.CONTOUR)
out.show()
# 壓花濾鏡效果
out=im.filter(ImageFilter.EMBOSS)
out.show()
out.save("output.jpg")
改變圖片大小
from PIL import Image
im=Image.open("myqrcode.jpg")
# 改變圖片大小,傳入一個 tuple
out=im.resize((100,100))
out.show()
out.save("output.jpg")
反轉圖片
from PIL import Image, ImageOps
im=Image.open("myqrcode.jpg")
# 轉為灰階的圖片
im = im.convert('L')
# 反轉圖片
out = ImageOps.invert(im)
out.show()
out.save("output.jpg")
下面範例將繪製 $y=x^2$ 的曲線:
import numpy as np
import matplotlib.pyplot as plot
# y = x 的平方
x = np.arange(-10, 10, 0.1)
y = np.square(x)
# 繪製曲線
plot.plot(x, y)
plot.show()
下面範例將繪製 $y=sin(x), 0 \le x \le 2\pi $ 的曲線:
import numpy as np
import matplotlib.pyplot as plt
# y = sin(x)
x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)
# 繪製曲線
ax=plt.plot(x, y)
plt.show()
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
# y = sin(x)
x = np.arange(0, 2*np.pi, 0.1)
y = np.sin(x)
# 建立 subplots
fig, sp = plt.subplots()
# 建立網格及圖標
sp.grid()
sp.set(xlabel='x', ylabel='y',
title='y=sin(x)')
# 繪製曲線
sp.plot(x, y)
plt.show()
# 匯出圖檔
fig.savefig("sin.png")
下面範例將繪製20個0~100的亂數分佈長條圖:
# 請先執行下列指令
# 在 JUPYTER NOTEBOOK 直接顯示圖形
%matplotlib inline
# 解決中文無法顯示
plt.rcParams['font.sans-serif'] = ['DFKai-sb']
# 讓字體變得清晰
%config InlineBackend.figure_format = 'retina'
import random
import matplotlib.pyplot as plt
# 產生 20 個 0~100 的亂數
亂數 = random.sample(range(0, 101), 20)
清單 = list(range(0, 101, 10))
plt.hist(亂數, 清單, histtype = "bar")
plt.xlabel("範圍")
plt.ylabel("亂數")
下面範例將繪製4個數量的占比原形圖:
%.1f%%
表示顯示1位小數。import matplotlib.pyplot as plt
項目= ["A", "B", "C", "D"]
數量 = [36, 36, 10, 3]
顔色 = ["green", "lightblue", "yellow", "orange"]
plt.pie(數量, labels=項目, colors=顔色, \
shadow=True,explode=(0, 0, 0.2, 0), \
autopct = "%.1f%%")
plt.axis("equal")
plt.show()
下面範例將繪製地理投影圖
import matplotlib.pyplot as plt
plt.figure()
plt.subplot(111, projection="aitoff")
plt.title("艾托夫投影")
plt.grid(True)
import matplotlib.pyplot as plt
plt.figure()
plt.subplot(111, projection="lambert")
plt.title("蘭伯特方位角等面積投影")
plt.grid(True)
下面範例將繪製 $Z=X^2+Y^2 $ 的3D曲面:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
# 建立 X 與 Y 矩陣
X, Y = np.meshgrid(X, Y)
# Z = X² + Y²
Z = X**2 + Y**2
# 建立 3D 繪製物件
ax = Axes3D(plt.figure())
# 繪製曲面
ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
plt.show()
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
# 建立 X 與 Y 矩陣
X, Y = np.meshgrid(X, Y)
# Z = X² + Y²
Z = X**2 + Y**2
# 建立 3D 繪製物件
ax = plt.figure().add_subplot(111, projection='3d')
# 繪製基本線框
ax.plot_wireframe(X, Y, Z, rstride=1, cstride=1)
plt.show()