2019年12月19日 星期四

[ Python 文章收集 ] Python Unpacking 實用技巧分享

Source From Here
Preface
Python 相較於其他程式語言,以能夠用簡潔的語法來達到相同的運算聞名,本篇要來教大家的Python Unpacking技巧,就是讓您在操作像 串列 (List)元組 (Tuple) 及 字典 (Dictionary) 等可疊代的資料型態時,能夠用簡潔且有效率的語法來取出其中的元素,進而做其他更複雜的運算。Unpacking 顧名思義就是將打包好的資料取出來,這邊整理了五個使用的情境,包含了:
* List Unpacking (串列開箱)
* Tuple Unpacking (元組開箱)
* For-Loop Unpacking (迴圈開箱)
* Swapping Variables Value (交換變數值)
* Unpacking Operator (開箱運算子)

List Unpacking (串列開箱)
在一般的情況下,我們要存取 串列 (List) 中的資料並且指派給變數時,通常會像下面範例這樣做:
>>> names = ["Mike", "Peter", "John"]
>>> print("first={}; second={}; third={}".format(names[0], names[1], names[2]))
first=Mike; second=Peter; third=John

這種寫法當我們要指派的變數越多時,就會顯得沒有效率,這時候就能夠 使用 Unpacking 的技巧,將 串列 (List) 中的資料指派給多個變數,如下範例:
>>> first, second, third = names
>>> print(f'first={first}; second={second}; third={third}')
first=Mike; second=Peter; third=John

這樣程式碼是不是簡潔多了呢。範例中有一個需要特別要注意的地方,串列 (List) 中的資料個數要與變數的個數一致,不然會發生例外錯誤:
>>> first, second = names
Traceback (most recent call last):
File "", line 1, in
ValueError: too many values to unpack (expected 2)

當串列中有大量的資料時,則可以獨立定義所需的變數個數來透過 Unpacking 的方式來指派資料,剩下的元素則可以使用 * 符號來進行打包的動作,如下範例:
>>> letters = list("ABCDRY")
>>> first, second, *others = letters
>>> print(f"first={first}; second={second}; others={others}")
first=A; second=B; others=['C', 'D', 'R', 'Y']

另一種變形的應用就是可取得 串列 (List) 中第一個元素及最後一個元素,剩下的同樣可以用 * 符號打包起來,如下範例:
>>> first, *others, last = letters
>>> print(f"first={first}; others={others}; last={last}")
first=A; others=['B', 'C', 'D', 'R']; last=Y

Tuple Unpacking (元組開箱)
串列 (List) 的 Unpacking 技巧同樣可以使用於 元組 (Tuple),除了可以將資料指派給多個變數外,也可以彈性的運用 * 符號來處理大量的資料,如下範例:
>>> names = ('Mike', 'Peter', 'John', 'Jack')
>>> first, second, third, fourth = names
>>> first, *others, last = names
>>> print(f'first={first}; others={others}; last={last}')
first=Mike; others=['Peter', 'John']; last=Jack

For-Loop Unpacking (迴圈開箱)
舉例來說,當我們透過 Python 的 For-Loop 迴圈讀取 串列 (List) 中的元素時,想要同時取得元素的索引值及資料,這時候可以搭配 enumerate() 方法及 Unpacking 的技巧來達成,如下範例:
>>> names = ("Mike", "Peter", "John")
>>> for name in enumerate(names):
... print(name)
...
(0, 'Mike')
(1, 'Peter')
(2, 'John')

從範例中的執行結果可以看到,在每一次迴圈的讀取時,enumerate() 方法會回傳一個 元組(Tuple) 資料型態,我們就可以直接在 For-Loop 迴圈的地方 Unpacking 元組 (Tuple) 的資料給兩個變數,來達到同時取得元素索引值及資料的效果,如下範例:
>>> for index, name in enumerate(names):
... print(f"{index}) {name}")
...
0) Mike
1) Peter
2) John

另一個使用情境就是在透過 Python 的 For-Loop 迴圈讀取 字典 (Dictionary) 中的元素時,我們使用的 items() 方法也是回傳一個 元組 (Tuple) 資料型態,所以同樣我們也可以利用 Unpacking 的技巧來同時取得 鍵 (Key) 及 值 (Value),如下範例:
>>> heights = {"Mike": 170, "Peter": 165}
>>> for name, height in heights.items():
... print(f"{name} with height as {height}")
...
Mike with height as 170
Peter with height as 165

Swapping Variables Value (交換變數值)
再來介紹一個 Unpacking 的使用情境,如果我們要互換兩個變數的值,在不使用 Unpacking 的技巧時,我們會這樣做:
>>> a = 15; b = 20
>>> c = a; a = b; b = c
>>> print(f'a={a}; b={b}')
a=20; b=15

首先多定義一個變數 c,然後把 a 的值先指派給 c,接著把b的值指派給 a,最後再把 c (當初 a 的值) 指派給 b,這樣就達到了兩個變數值互換的效果。而我們使用了Python 的 Unpacking 技巧後,只需寫一行,如下範例:
>>> a = 15; b = 20
>>> a, b = b, a
>>> print(f'a={a}; b={b}')
a=20; b=15

Unpacking Operator (開箱運算子)
Unpacking Operator 分為:
* 符號:可用於任何可疊代的 (Iterable) 物件。
** 符號:只能用於 字典 (Dictionary) 物件 。

主要用途為分解 可疊代的 (Iterable) 物件元素,在進行建立或合併時非常的實用。首先來看 * 符號的使用範例:
>>> values = [*range(10)]
>>> print(f'values: {values}')
values: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> combined = [*values, *"Python"]
>>> print(f'combined: {combined}')
combined: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'P', 'y', 't', 'h', 'o', 'n']

接著我們來看 ** 符號運用於 字典 (Dictionary) 資料型態的範例:
>>> heights = {"Mike": 170, "Peter": 165}
>>> weights = {"Mike": 65, "John": 70}
>>> combined = {**heights, **weights, "other": 1}
>>> print(f'combined: {combined}')
combined: {'Mike': 65, 'Peter': 165, 'John': 70, 'other': 1} // "Mike" is overwrite from 170 to 65

從執行結果中可以看到,當合併 字典(Dictionary) 時,相同的 鍵(Key) 會被之後出現的 鍵(Key) 覆蓋,所以只印出 Mike 的體重而沒有身高。


Supplement
如何使用 Python 進行字串格式化

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...