Python4️⃣:0小白基礎之——流程控制專題

唐樽發表於2020-12-18


流程控制與程式碼的執行順序息息相關,流程控制相關的關鍵字,
如 if , elif , for , while , break , continue , else , return , yield , pass 等。

1、if 用法

if 後的語句指定了一個條件,若滿足 if 則, : 後的語句成立。
如果 if 不滿足,再使用 elif 判斷其他情況,可以一直寫 elif ,
若是最後一個判斷條件,可使用 else ,其基本結構為:
if A:
print('condition A meets')
elif B:
print('condition B meets')
elif C:
print('condition C meets')
else:
print('other conditions meets')

2、 for 用法

Python的 for 除了具備控制迴圈次數外,
還能直接迭代容器中的元素,
控制迴圈次數還能直接操作容器內的元素。
nums = [1,[2,3],5,5,[8,6,64]]
for i in range(1, len(nums)):
    print(i)

3、 while,break,continue

while 後面緊跟一個判斷條件,若滿足條件則會一直迴圈,直到不滿足條件時退出。
但這不是絕對的,如果while後的語句塊內含有 break ,
即便條件依然滿足,但遇到 break 也會一樣退出。

如下檢測輸入是否為整數,直到輸入整數時,執行 break 退出 while 迴圈:

while True: 
	a = input('please input an Integer: ')
	try:
		ai = int(a)
		print('輸入了一個整數 %d ,input 結束' % (ai,))
		break
	except:
		print("%s isn't a Integer" % (a,))
continue 與最近的迴圈語句 for 或 while 組合,
表示接下來迴圈體內的語句不執行,重新進入下一次遍歷。
nums = [1,2,-1]
for num in nums:
    if num <= 0:
        continue
    print('得到一個大於0的數 %d' % (num))

4、 for 使用注意

for 語句遍歷容器型別或可迭代型別時,
如果涉及到增加、刪除元素,就需要小心。
比如請先看下面的例子:
刪除列表中的某個元素值,可能有重複,要求元素順序不變,
空間複雜度為O(1),如果像下面這樣寫就會有問題。
def delItems(nums, target):
	for item in nums:
	if item == target:
		nums.remove(item)
	return nums
	
r = delItems([2, 1, 3, 1, 1, 3], 1)
print(r)
不管是Python, Java, C++,列表或陣列刪除元素時,
其後面的元素都會逐次前移1位,但是 for 依然會正常迭代,
因此“成功”規避了相鄰的後面元素1。

![在在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
刪除元素1
下步最關鍵:直譯器自動前移刪除位置後的所有元素

在這裡插入圖片描述
在這裡插入圖片描述

這樣元素 3 成功逃避是否與目標值相等的檢查。
結論:命中目標處的後一個位置都逃避了是否與目標值相等的檢查,
所以一旦有連續目標值,必然就會漏掉,進而觸發上面的bug。
明白上面這個原因後,重新再改寫一遍刪除所有重複元素的程式碼,
下面程式碼不再使用 for 直接遍歷元素。
(再說一遍:增刪元素原來迭代器發生改變,所以會導致異常行為),
而是使用索引訪問:
def delItems(nums, target): 
    i = 0
    while i < len(nums):
        if nums[i] == target:
            del nums[i]
            i -= 1
        i += 1
    return nums
r = delItems([2, 1, 3, 1, 1, 3], 1)
print(r) # [2,3,3]
如果元素等於 target ,從陣列 nums 中刪除 nums[i] ,
刪除後直譯器自動將 i 後的元素都前移1位。
據此,巧妙的控制 i 值,一旦命中立即 i 減去1,這樣確保不漏檢查。

5、 range 序列

range 在Python中經常用於生成一串數字序列,
對剛入門Python的朋友想嘗試列印其中的值:
for i in range(10): 
    print(i,end=",")
range 函式的返回值為什麼能與 for 結合?
型別為 Iterable 的物件都可與 for 結合,
下面確認 range(10) 返回值是否為 Iterable :
rom collections.abc import Iterable
isinstance(range(10),Iterable)
# 輸出 True ,它是 Iterable 型別
range 函式為了高效節省記憶體,一次只返回一個值,
而不是直接將構成序列的全部元素載入到記憶體。

Python裡的range不支援建立浮點序列,所以為了更加清楚的展示 range 的原理,編寫一個建立浮點數的序列 frange :

fr = frange(0, 1.,0.2)
for i in fr:
    print("{:.2f}".format(i),end=",")

6、 Python特色:迴圈與else

6.1 for 能和 else 組對
Python一大特色: while , for 能和 else 組對,不僅如此, 
try except 和 else 也能組對,下面介紹它們存在的價值。

找出2到15的所有素數,如果不是素數列印出一對因子,實現程式碼如下:

for num in range(2, 16):
    for item in range(2, num):
        if num % item == 0:
            print('%d = %d*%d ' % (num, item, num // item))
            break
    else:
        print("%d 是素數" % (num))
 for 和 else 組對的功能: for 遍歷完成後執行 else ,
 但是觸發 break 後, else 不執行。
6.2 try , except 和 else 組對
while True:
    try:
        a = int(input('請輸入一個整數: '))
    except ValueError: 
        print('input value is not a valid number') 
    else: 
        if a % 2 == 0: 
            print('輸入的 %d 是偶數' %(a,)) 
        else: 
            print('輸入的 %d 是奇數' %(a,)) 
        break
try 保護的程式碼正常通過後, else 才執行。
放到 else 中意味著這塊程式碼不必受保護,
因為它不可能觸發 ValueError 這樣的異常。

7、 pass 與介面

Python中最特別的關鍵字之一便是 pass ,
它放在類或函式裡,表示類和函式暫不定義。
class PassClass:
	pass
def PassFun():
	pass
	
如上實現最精簡的類和函式定義。

8、 return 和 yield

程式遇到 return 和 yield 都是立即中斷返回。
那麼 yield 和 return 又有什麼不同呢?
與 return 不同, yield 中斷返回後,
下一次迭代會進入到yield後面的下一行程式碼,
而不像return下一次執行還是從函式體的第一句開始執行。	
# 實現累加求和
def f(n):
    a,b = 1,1
    for _ in range(n):
        yield a
        a, b = b, a+b
        
for i in f(10):
    print(i)

第一次 yield 返回 1,第二次yield返回 a+b=2的值,第三次…以此累加。

9、 短路原則

布林運算子 and 和 or 也被稱為短路運算子:
它們的引數從左至右解析,一旦可以確定結果解析就會停止。
A and B : 如果 A 不成立,B 不會執行
A or B : 如過 A 成立,B不會執行
a = ''
b = a and 'i will not execute'
print(b)

列印結果為空,因為 and 運算子從左到右檢查,
一旦 a 為空即為假,則結果已確定為假,
'i will not execute' 被短路。

c = 'python'
d = c or 'i will not execute'
print(d)

列印結果為:python,因為 or 運算子從左到右檢查,
一旦c為真則結果已確定為真, 所以'i will not execute' 被短路。

相關文章