條件與流程控制

條件判斷式

項目 條件判斷式
等於 a == b
不等於 a != b
小於或等於 a <= b
大於 a > b
大於或等於 a >= b

條件判斷式主要是由比較運算子構成,最常用在 if流程控制 及 while 迴圈中使用。

if 流程控制

單一條件 if

選擇結構 if 的語法如下:

if 條件式:
   縮排的程式碼(至少一列)
   縮排的程式碼

當條件式結果為True時,執行縮排的程式碼,例如:

In [1]:
分數 = 80
if 分數 >= 60:
  print("及格")
及格

當if所控制的程式碼只有一列時,則可以簡化為一列:

In [2]:
if 分數 >= 60: print("及格")
及格

雙條件 if...esle

if...esle 選擇結構的語法如下:

if 條件式:
   縮排的程式碼(至少一列)
else:
   縮排的程式碼(至少一列)

當條件式結果為True時,執行 if 後縮排的程式碼,若爲 False 執行 else 後縮排的程式碼。

In [3]:
分數 = 80
if 分數 >= 60:
  print("及格")
else:
  print("不及格")
及格

當各條件所控制的程式碼都只有一列時,則可以簡化為一列(注意無冒號):

In [4]:
print("及格") if 分數 >= 60 else print("不及格")
及格

多條件 if...elif...else

if...elif...else 選擇結構的語法如下:

if 條件式A:
   縮排的程式碼(至少一列)
elif 條件式B:
   縮排的程式碼(至少一列)
elif 條件式C:
   縮排的程式碼(至少一列)
else:
   縮排的程式碼(至少一列)

elif 區塊的數量可以是無、1個或數個,其執行流程為由上而下逐一比對條件式,只要條件式結果為True時,便執行其後的縮排的程式碼,然後條離整個 if 區塊;若所有條件式都不滿足,則執行 else 後的程式碼。

In [5]:
分數 = 80
if 分數 > 60:
  print("及格")
elif 分數 == 60:
  print("剛好及格")
else:
  print("不及格")
及格

當各條件所控制的程式碼都只有一列時,則可以簡化為一列(注意無冒號):

In [6]:
print("及格") if 分數 > 60 else print("剛好及格") if 分數 == 60 else print("不及格")
及格

邏輯運算子and / or

if 搭配第三章所探討的邏輯運算子,可以完成更複雜的條件控制。

In [7]:
a = 200
b = 33
c = 500

if a > b and c > a:
  print("True")
else:
  print("False")

if a > b or a > c:
  print("True")
else:
  print("False")
True
True

迴圈

Python有兩個迴圈命令:

  • while 迴圈
  • for 迴圈

迴圈使用建議:

  • while 迴圈適用在一個條件成立下
  • for 迴圈適用在一個範圍之內

while 迴圈

while 迴圈的語法如下:

while 條件式:
   縮排的程式碼(至少一列)
else:
   縮排的程式碼(至少一列)

當條件式結果為True時,重複執行 while 後縮排的程式碼,直到條件式結果為False。 else: 區塊可以省略,當離開迴圈時執行。

In [8]:
i = 0
while i < 5:
  print(i, end=' ')
  i += 1
0 1 2 3 4 
In [9]:
i = 0
while i < 5:
  print(i, end=' ')
  i += 1
else:
  print("迴圈已結束")
0 1 2 3 4 迴圈已結束

for 迴圈

for 迴圈的語法如下:

for 變數 in 可迭代物件:
   縮排的程式碼(至少一列)
else:
   縮排的程式碼(至少一列)

當 for 迴圈開始遍歷可迭代物件的每一項目,並將該項目指派給變數,然後執行 for 後縮排的程式碼,直到可迭代物件遍歷到最後的項目。 else: 區塊可以省略,當離開for迴圈時執行。

range( ) 函數

可迭代物件可透過range()函數產生,range()函數預設從 0 開始遞增。

In [10]:
for x in range(5):
  print(x, end=' ')
0 1 2 3 4 
In [11]:
# range(起始值, 終止值)
for x in range(2, 5):
  print(x, end=' ')
2 3 4 
In [12]:
# range(起始值, 終止值, 增量值)
for x in range(2, 10, 2):
  print(x, end=' ')
2 4 6 8 
In [13]:
for x in range(5):
  print(x, end=' ')
else:
  print("迴圈已結束")
0 1 2 3 4 迴圈已結束

遍歷清單及字串

可迭代物件也可以是list、tuple、dict、set或字串。

In [14]:
myLlist = ["香蕉", "蘋果", "鳳梨"]
for x in myLlist:
  print(x, end=' ')
香蕉 蘋果 鳳梨 
In [15]:
for x in "奇異果":
  print(x, end=' ')
奇 異 果 

break 及 continue

  • break 語句用在强制停止迴圈
  • continue 語句用在停止當前迭代,然後繼續下一個
In [16]:
i = 0
while i < 5:
  if i==3: 
    break
  print(i, end=' ')
  i += 1
0 1 2 
In [17]:
i = 0
while i < 5:
  if i==3: 
    i += 1
    continue  
  print(i, end=' ')
  i += 1
0 1 2 4 
In [18]:
for i in range(5):
  if i==3: break
  print(i, end=' ')
0 1 2 
In [19]:
for i in range(5):
  if i==3: continue  
  print(i, end=' ')
0 1 2 4 

無窮迴圈

  • 下列程式碼當 i==3 時, i += 1 永遠都不會被執行,會造成條件式永遠滿足,迴圈將不會終止(因 i 永遠等於 3)
  • 無窮迴圈屬於嚴重的邏輯錯誤,應當要避免發生
i = 0
while i < 5:
  if i==3: continue  
  print(i, end=' ')
  i += 1

Python 内建模組

模組(module)式一個以.py為副檔名的檔案,其中會定義了變數、函數或類別,當要使用模組的功能時,可以透過import 模組名稱指令來載入。

作業系統模組 (OS)

os模組包含作業系統的操作功能,如檔案管理、目錄等,與具體的作業系統無關

In [11]:
import os

#取得目前的作業系統
# Windows 返回 nt 
# Linux   返回 posix
print(os.name) 
nt
In [12]:
import os

#取得目前的工作目錄
print(os.getcwd())
C:\Users\csliu68\Desktop\教材編輯\Python
In [14]:
import os

#取得目前目錄下所有的檔案和目錄名稱清單
print(os.listdir())
['.ipynb_checkpoints', '0.mp3', '1.mp3', '2.mp3', '3.mp3', 'aa', 'chinese.mp3', 'file', 'hello.mp3', 'myqrcode.jpg', 'output', 'output.jpg', 'Python-1.ipynb', 'Python-2.html', 'Python-2.ipynb', 'Python-3.html', 'Python-3.ipynb', 'Python-4.html', 'Python-4.ipynb', 'Python-5.ipynb', 'save', 'sin.png', 'test.png']
In [21]:
import os

#移除目錄
print(os.removedirs("新目錄"))

#建立目錄
print(os.mkdir("新目錄"))
None
None

calendar 日曆

In [48]:
import calendar
print(calendar.month(2020, 1))
    January 2020
Mo Tu We Th Fr Sa Su
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

透過 as 可替模組取個簡短的別名

In [49]:
import calendar as cal
print(cal.month(2020, 1))
    January 2020
Mo Tu We Th Fr Sa Su
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

透過 from...import... 可載入模組特定的類別或函數,如下例,使用month()不需再加上模組名稱:

In [50]:
from calendar import month
print(month(2020, 1))
    January 2020
Mo Tu We Th Fr Sa Su
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

日期與時間

要使用日期與時間,需要導入 datetime 模組,並呼叫 strftime()函數,該函數的輸出格式指令如下表:

指令 説明 執行結果範例
%a 星期縮寫 Wed
%A 星期 Wednesday
%w 星期的數字(0-6)
星期日為 0
3
%d 日期(01-31) 31
%b 月份縮寫 Dec
%B 月份 December
%m 月份的數字(01-12) 12
%y 年份末2碼 18
%Y 年份 2018
%p AM/PM PM
%H 時(00-23) 17
%I 時(00-12) 05
%M 分(00-59) 41
%S 秒(00-59) 08
In [96]:
import datetime

# 取得執行端的日期及時間
x = datetime.datetime.now()

# 顯示日期及時間
print(x)

# 顯示當前年份
print(x.year)
2020-05-06 18:15:40.067521
2020
In [97]:
import datetime

# 取得執行端的日期及時間
x = datetime.datetime.now()

# 顯示完整星期名稱
print(x.strftime("%A"))

# 顯示星期名稱縮寫
print(x.strftime("%a"))
Wednesday
Wed
In [98]:
import datetime

# 創建一個自訂日期對象:
x = datetime.datetime(2020, 5, 17)
print(x)
2020-05-17 00:00:00

統計模組

模組提供了替數值資料計算基本統計量(包括平均、中位數、變異量等)的功能。

In [105]:
import statistics
資料 = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]

# 平均值
print("平均值", statistics.mean(資料))

# 中位數
print("中位數", statistics.median(資料))

#變異量
statistics.variance(data)
print("變異量", statistics.median(資料))
平均值 1.6071428571428572
中位數 1.25
變異量 1.25

隨機亂數

Python 內建 random 模組,可用於產生隨機亂數:

In [20]:
import random

#語法:random.randint(開始,結束)
#顯示 0 到 9 之間的隨機整數
print(random.randint(0, 9))

#語法:
#random.randrange(開始,結束,間距)
#顯示 0 到 9 之間的隨機數偶數
print(random.randrange(0, 9, 2))

#顯示 0 到 1 間的隨機數浮點數
print(random.random())
5
8
0.1896871038511676

隨機選取清單項目

In [72]:
import random
random.choice(['小明', '小王', '小陳', '小黃', '小珍'])
Out[72]:
'小珍'

隨機洗牌

In [73]:
import random
名單=['小明', '小王', '小陳', '小黃', '小珍']
random.shuffle(名單)
print(名單)
['小明', '小珍', '小陳', '小王', '小黃']

抽籤程式

In [74]:
import random

起始 = int(input("請輸入起始值:"))
結束 = int(input("請輸入結束值:"))
人數 = int(input("請輸入抽獎人數:"))

print("獲獎名單為:")
for i in range(人數):
  print(random.randint(起始, 結束))
請輸入起始值:1
請輸入結束值:10
請輸入抽獎人數:5
獲獎名單為:
3
8
6
3
8

抽籤程式改良版

上一個範例會有重複中籤的問題,本例子進一步將已中籤者移除,避免重複中籤

In [75]:
import random

起始 = int(input("請輸入起始值:"))
結束 = int(input("請輸入結束值:"))
人數 = int(input("請輸入抽獎人數:"))

候選清單=list(range(起始, 結束+1))

print("獲獎名單為:")
for i in range(人數):
  # 隨機抽籤
  中籤者=random.choice(候選清單)
  print(中籤者)

  # 移除已中籤者
  候選清單.remove(中籤者)
請輸入起始值:1
請輸入結束值:10
請輸入抽獎人數:5
獲獎名單為:
4
1
9
2
5

猜數字遊戲

In [76]:
import random

答案 = random.randint(0, 10)
print("請輸入 Q 跳離程式")
while True:
    gue = input("請猜一個數字(0-10):")
    if gue == "Q" or gue == "q":
        break
    elif int(gue) == 答案:
        print("恭禧你,猜中了")
        break
    elif int(gue) > 答案:
        print("你猜的數字太大了")
    else:
        print("你猜的數字太小了")

print("歡迎下次再來玩!")
請輸入 Q 跳離程式
請猜一個數字(0-10):1
你猜的數字太小了
請猜一個數字(0-10):5
你猜的數字太大了
請猜一個數字(0-10):4
你猜的數字太大了
請猜一個數字(0-10):3
恭禧你,猜中了
歡迎下次再來玩!

迷宮

In [ ]:
import random

for i in range(1000):
  print(random.choice('\u2571\u2572'), end='')

函數

函數使用 def 關鍵字定義,是在被呼叫時才會運行的程式區塊,並可以選擇性的傳遞參數給函數,也可以選擇性的回傳參數。 函數具有以下的優點:

  • 可重複使用,同樣的程式邏輯不需要重複撰寫。
  • 可以將同樣的程式邏輯整理成函數,讓程式更精簡,也會提供程式的可讀性。
  • 將程式拆解成函數後,可以提供程式的邏輯性及正確性,已除錯完成的函數便可不需要在重複除錯,可以簡化程式開發及維護流程。
In [77]:
# 基本函數定義
def my_function():
  print("Welcome")

# 呼叫函數
my_function()
Welcome

參數

在函數名稱後的括號內可指定參數,可以根據需要添加任意數量的參數,只需用逗號分隔即可:

In [78]:
def 自訂函數(參數):
  print(參數)

# 呼叫函數(傳遞參數)
自訂函數("樂活學程式")
樂活學程式

未知數量的參數

如果不知道函數將傳遞多少個參數,可以在函數定義的參數名稱前添加*,函數將接收到一個清單參數:

In [79]:
def 自訂函數(*參數):
  for 項目 in 參數:
    print(項目)

# 呼叫函數(傳遞參數)
自訂函數("樂活", "學", "程式")
樂活
學
程式

如果不知道函數將傳遞多少個參數,可以在函數定義的參數名稱前添加**,函數將接收到一個字典參數:

In [80]:
def 自訂函數(**參數):
  print(參數)

# 呼叫函數(傳遞參數)
自訂函數(title="樂活", to="學", content="程式")
{'title': '樂活', 'to': '學', 'content': '程式'}

參數的預設值

In [81]:
# message參數的預設值為"這是預設值"
def 自訂函數(參數="這是預設值"):
  print(參數)

# 呼叫函數(無傳遞參數)
自訂函數()

# 呼叫函數(有傳遞參數)
自訂函數("這是傳遞的參數")
這是預設值
這是傳遞的參數

傳遞清單參數

任何資料類型皆可作爲參數傳送到函數(例如字串、數字、列表、字典等):

In [82]:
def 自訂函數(參數):
  for 項目 in 參數:
    print(項目)

# 呼叫函數(傳遞 list 參數)
自訂函數(["樂活", "學", "程式"])
樂活
學
程式

回傳值

要讓函數回傳值,請使用 return 語句

In [83]:
def 自訂函數(x):
  return 5 * x

print(自訂函數(3))
print(自訂函數(6))
15
30
In [84]:
# 回傳清單
def 自訂函數():
  x=["樂活", "學", "程式"]
  return x

#回傳的清單將指派給 y
y=自訂函數() 
print(y)
['樂活', '學', '程式']
In [85]:
# 回傳多個值
def 自訂函數():
  a=10
  b=20
  return a, b

#回傳的值分別指派給 x, y
x, y=自訂函數() 
print(x, y)
10 20

傳值(Call by Value)

  • 基本的資料形態(如 int, float, str等)及不可改變内容的物件(如 tuple)採用傳值方式傳遞參數。
  • 傳遞的參數值會複製到函數的區域變數,兩者在各自獨立的記憶空間。
In [86]:
def 自訂函數(y):
  y = 10

# x 為整數形態,採用複製方式傳遞參數
x = 5
自訂函數(x)

# 執行後, x 内容不會改變
print(x)
5
In [87]:
# 交換 x y 的值
def 交換(x, y):  
  tmp = y
  y = x
  x = tmp

a = 10
b = 20
交換(a, b)

#執行後,a b的内容不變
print(a, b)
10 20

傳參考 (Call by Object Reference)

  • 可改變内容的物件資料形態會採用傳參考方式傳遞參數。
  • 傳遞的參數與函數的區域變數會參考到同一記憶空間。
In [88]:
# y 與 x 會參考同一記憶空間
def 自訂函數(y):  
  y[0] = 10

# x 為清單,採用傳參考方式傳遞
x = [5]         
自訂函數(x)

# x 内容確實被改變
print(x)
[10]
In [89]:
# 交換 x y 的值
def 交換(x, y):  
  tmp = y[0]
  y[0] = x[0]
  x[0] = tmp


a = [10]
b = [20]
交換(a, b)

# 執行完後,a b的内容確實會交換
print(a, b)
[20] [10]
In [90]:
# 個人資料 為字典形態
個人資料 = {
  "名字": "强森",
  "電話": "03-543210",
  "出生年": 1964
}              

# y 與 x 會參考同一記憶空間
def 自訂函數(資料):  
  資料["名字"] = "名字被改了"

# 個人資料 為字典形態,採用傳參考方式傳遞
自訂函數(個人資料)
print(個人資料)
{'名字': '名字被改了', '電話': '03-543210', '出生年': 1964}

全域變數與區域變數

在函數外部創建的變數稱為全域變數,全域變數可以在函數內部和外部使用。在函數内部創建的變數或傳遞的參數稱為區域變數,區域變數只可以在函數內部使用。

In [91]:
def 自訂函數():
  print(x)

x = "我是全域變數"
自訂函數()
我是全域變數

函數內部創建的變數是區域變數,只能在函數內部使用。

def 自訂函數():
  區域變數 = "我是區域變數"

print(區域變數)
   
NameError: name '區域變數' is not defined  
名稱錯誤:名稱 "區域變數" 未定義**

具有相同名稱的全域變數與區域變數將在各自獨立記憶體執行。

In [92]:
def 自訂函數():
  x = "我是區域變數"
  print(x)

x = "你好"
自訂函數()
我是區域變數

要在函數內部創建全域變數,可以使用 global 關鍵字。

In [93]:
def 自訂函數():
  global x
  x = "這是全域變數"
  print(x)

自訂函數()
print(x)
這是全域變數
這是全域變數

簡單的函數宣告(Lambda)

In [94]:
def add(x, y):
  return x + y

add(3, 5)
Out[94]:
8
In [95]:
add=lambda x, y: x + y

add(3, 5)
Out[95]:
8
🏠