天天看點

Python學習:條件和循環,基本功

在學習了清單、元祖、字典、集合和字元串等一系列 Python 的基本資料類型後,如何把這一個個基本的資料結構類型串接起來,就需要條件和循環了。

一、條件語句

Python 的條件語句,用法很簡單。比如,想要表示 y=|x|這個函數,那麼相應的代碼便是:

# y = |x|
if x < 0:
    y = -x
else:
    y = x
           

需要注意的是,在條件語句的末尾必須加上冒号(:),這是 Python 特定的文法規範。

由于 Python 不支援 switch 語句,是以,當存在多個條件判斷時,需要用 else if 來實作,這在 Python 中的表達是elif。文法如下:

if condition_1:
    statement_1
elif condition_2:
    statement_2
...
elif condition_i:
    statement_i
else:
    statement_n
           

整個條件語句是順序執行的,如果遇到一個條件滿足,比如 condition_i 滿足時,在執行完 statement_i 後,便會退出整個 if、elif、else 條件語句,而不會繼續向下執行。

不過要注意,if 語句是可以單獨使用的,但 elif、else 都必須和 if 成對使用。

另外,在進行條件判斷時, 不少人喜歡省略判斷的條件,比如寫成下面這樣:

if s: # s is a string
    ...
if l: # l is a list
    ...
if i: # i is an int
    ...
... 
           

關于省略判斷條件的常見用法:

Python學習:條件和循環,基本功

不過,切記,在實際寫代碼時,除了 boolean 類型的資料,條件判斷最好是顯性的。比如,在判斷一個整型數是否為 0 時,我們最好寫出判斷的條件:

if i != 0:
    ...
           

而不是隻寫出變量名:

if i:
    ...
           

二、循環語句

所謂循環,顧名思義,本質上就是周遊集合中的元素。和其他語言一樣,Python 中的循環一般通過 for 循環和 while 循環實作。

比如,有一個清單,需要周遊清單中的所有元素并列印輸出,代碼如下:

l = [1, 2, 3, 4]
for item in l:
    print(item)

1
2
3
4
           

其實,Python 中的資料結構隻要是可疊代的(iterable),比如清單、集合等等,那麼都可以通過下面這種方式周遊:

for item in <iterable>:
    ...
           

這裡需要單獨強調一下字典。字典本身隻有鍵是可疊代的,如果我們要周遊它的值或者是鍵值對,就需要通過其内置的函數 values() 或者 items() 實作。其中,values() 傳回字典的值的集合,items() 傳回鍵值對的集合。

d = {'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'}
for k in d: # 周遊字典的鍵
    print(k)

name
dob
gender

for v in d.values(): # 周遊字典的值
    print(v)

jason
2000-01-01
male    

for k, v in d.items(): # 周遊字典的鍵值對
    print('key: {}, value: {}'.format(k, v))

key: name, value: jason
key: dob, value: 2000-01-01
key: gender, value: male 
           

通過集合中的索引周遊元素,通常通過 range() 這個函數,拿到索引,再去周遊通路集合中的元素。比如下面的代碼,周遊一個清單中的元素,當索引小于 5 時,列印輸出:

l = [1, 2, 3, 4, 5, 6, 7]
for index in range(0, len(l)):
    if index < 5:
        print(l[index])  
              
1
2
3
4
5
           

當我們同時需要索引和元素時,還有一種更簡潔的方式,那就是通過 Python 内置的函數 enumerate()。用它來周遊集合,不僅傳回每個元素,并且還傳回其對應的索引,這樣一來,上面的例子就可以寫成:

l = [1, 2, 3, 4, 5, 6, 7]
for index, item in enumerate(l):
    if index < 5:
        print(item)  
             
1
2
3
4
5
           

在循環語句中,我們還常常搭配 continue 和 break 一起使用。所謂 continue,就是讓程式跳過目前這層循環,繼續執行下面的循環;而 break 則是指完全跳出所在的整個循環體。在循環中适當加入 continue 和 break,往往能使程式更加簡潔、易讀。

比如,給定兩個字典,分别是産品名稱到價格的映射,和産品名稱到顔色清單的映射。我們要找出價格小于 1000,并且顔色不是紅色的所有産品名稱和顔色的組合。如果不用 continue,代碼應該是下面這樣的:

# name_price: 産品名稱 (str) 到價格 (int) 的映射字典
# name_color: 産品名字 (str) 到顔色 (list of str) 的映射字典
for name, price in name_price.items():
    if price < 1000:
        if name in name_color:
            for color in name_color[name]:
                if color != 'red':
                    print('name: {}, color: {}'.format(name, color))
        else:
            print('name: {}, color: {}'.format(name, 'None'))
           

而加入 continue 後,代碼顯然清晰了很多:

# name_price: 産品名稱 (str) 到價格 (int) 的映射字典
# name_color: 産品名字 (str) 到顔色 (list of str) 的映射字典
for name, price in name_price.items():
    if price >= 1000:
        continue
    if name not in name_color:
        print('name: {}, color: {}'.format(name, 'None'))
        continue
    for color in name_color[name]:
        if color == 'red':
            continue
        print('name: {}, color: {}'.format(name, color))
           

我們可以看到,按照第一個版本的寫法,從開始一直到列印輸出符合條件的産品名稱和顔色,共有 5 層 for 或者 if 的嵌套;但第二個版本加入了 continue 後,隻有 3 層嵌套。

對于 while 循環,原理也是一樣的。它表示當 condition 滿足時,一直重複循環内部的操作,直到 condition 不再滿足,就跳出循環體。

while condition:
    ....
           

很多時候,for 循環和 while 循環可以互相轉換,比如要周遊一個清單,我們用 while 循環同樣可以完成:

l = [1, 2, 3, 4]
index = 0
while index < len(l):
    print(l[index])
    index += 1
           

通常來說,如果你隻是周遊一個已知的集合,找出滿足條件的元素,并進行相應的操作,那麼使用 for 循環更加簡潔。但如果你需要在滿足某個條件前,不停地重複某些操作,并且沒有特定的集合需要去周遊,那麼一般則會使用 while 循環。

同時需要注意的是,for 循環和 while 循環的效率問題。比如下面的 while 循環:

i = 0
while i < 1000000:
    i += 1
           

和等價的 for 循環:

for i in range(0, 1000000):
    pass
           

要知道,**range() 函數是直接由 C 語言寫的,調用它速度非常快。**而 while 循環中的“i += 1”這個操作,得通過 Python 的解釋器間接調用底層的 C 語言;并且這個簡單的操作,又涉及到了對象的建立和删除(因為 i 是整型,是 immutable,i += 1 相當于 i = new int(i + 1))。是以,顯然,for 循環的效率更勝一籌。

注意:如果想在for循環中從一個小數到另一個小數,可用np.arange()

可參考https://blog.csdn.net/weixin_44052055/article/details/108358654

三、條件與循環的複用

在閱讀代碼的時候,你應該常常會發現,有很多将條件與循環并做一行的操作,例如

expression1 if condition else expression2 for item in iterable
           

将這個表達式分解開來,其實就等同于下面這樣的嵌套結構:

for item in iterable:
    if condition:
        expression1
    else:
        expression2
           

而如果沒有 else 語句,則需要寫成:

expression for item in iterable if condition
           

舉個例子,比如我們要繪制 y = 2*|x| + 5 的函數圖像,給定集合 x 的資料點,需要計算出 y 的資料集合:

再比如我們在處理檔案中的字元串時,常常遇到的一個場景:将檔案中逐行讀取的一個完整語句,按逗号分割單詞,去掉首位的空字元,并過濾掉長度小于等于 3 的單詞,最後傳回由單詞組成的清單。這同樣可以簡潔地表達成一行:

text = ' Today,  is, Sunday'
text_list = [s.strip() for s in text.split(',') if len(s.strip()) > 3]
print(text_list)

['Today', 'Sunday']
           

當然,這樣的複用并不僅僅局限于一個循環。比如,給定兩個清單 x、y,要求傳回 x、y 中所有元素對組成的元祖,相等情況除外。

這樣的寫法就等價于:

l = []
for xx in x:
    for yy in y:
        if xx != yy:
            l.append((xx, yy))
           

由兩個清單attributes和values,然後針對values中每一組子清單value,輸入器和attributes中的鍵對應後的字典,最後傳回字典組成的清單。

attributes = ['name', 'dob', 'gender']
values = [['jason', '2000-01-01', 'male'], 
['mike', '1999-01-01', 'male'],
['nancy', '2001-02-01', 'female']
]

# expected outout:
[{'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'}, 
{'name': 'mike', 'dob': '1999-01-01', 'gender': 'male'}, 
{'name': 'nancy', 'dob': '2001-02-01', 'gender': 'female'}]
           

分行的:

out = []
for value in values:
    result = {}
    for index in range(len(value)):
        result[attributes[index]] = value[index]
    out.append(result)
print(out)
           

一行的:

out = [{attributes[i]: value[i] for i in range(len(attributes))} for value in values ]
print(out)
           

使用zip函數的一行的:

[dict(zip(attributes, value)) for value in values]

[{'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'}, {'name': 'mike', 'dob': '1999-01-01', 'gender': 'male'}, {'name': 'nancy', 'dob': '2001-02-01', 'gender': 'female'}]
           

zip函數:接受任意多個(包括0個和1個)序列作為參數,傳回一個tuple清單。

使用zip建立字典:

key = 'abcde'

value = range(1, 6)

d = dict(zip(key, value))
           

周遊字典: keys() 、values() 、items():

for key,value in d.items():
    print(key, value)

a 1
b 2
c 3
d 4
e 5
           
d.items()

dict_items([('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)])
           

參考:《Python核心技術與實戰》