為什麼要講解包
因為我覺得解包是 Python 的一大特性,大大提升了程式設計的效率,而且適用性很廣
啥是解包
- 個人通俗理解:解開包袱,拿出東西
- 正確理解:將元素從可迭代物件中一個個取出來
- python 中,解包是自動完成的
最簡單的解包栗子
a, b, c = [1, 2, 3] print(a, b, c) # 輸出結果 1 2 3
列表有 3 個元素,此時也需要 3 個變數去接,否則會報錯
a, b = [1, 2, 3] # 輸出結果 a, b = [1, 2, 3] ValueError: too many values to unpack (expected 2)
太多值無法解包
重點
- 除了列表可以解包,任何可迭代物件都支援解包
- 比如:列表、元組、字典、集合、字串、生成器,只要實現了 __next__ 方法的物件都是可迭代物件
可迭代物件詳解
https://www.cnblogs.com/poloyy/p/14658433.html
各種解包栗子
元組解包
>>> a,b,c = (1,2,3) >>> a 1 >>> b 2 >>> c 3
字串解包
>>> a,b,c = "abc" >>> a 'a' >>> b 'b' >>> c 'c'
集合解包
>>> a,b,c = {1,2,3} >>> a 1 >>> b 2 >>> c 3
字典解包
>>> a,b,c = {"a":1, "b":2, "c":3} >>> a 'a' >>> b 'b' >>> c 'c'
字典解包後,只會把字典的 key 取出來
多變數賦值
>>> a, b = 1, 2 >>> a 1 >>> b 2
- 其實也是元組解包
- 元組在 = 右邊的時候,可以忽略 ( )
生成器解包
# 生成器 a, b, c = (x + 1 for x in range(3)) print(a, b, c) # 輸出結果 1 2 3
生成器詳解文章
https://www.cnblogs.com/poloyy/p/14664538.html
解決變數數不等於右側可迭代物件中元素的個數
上面提到了這個報錯問題
a, b = [1, 2, 3] # 輸出結果 a, b = [1, 2, 3] ValueError: too many values to unpack (expected 2)
Python3 提供瞭解決方案
# 多變數 a, b, *c = [1, 2, 3, 4, 5] print(a, b, c) # 輸出結果 1 2 [3, 4, 5]
- 在某個變數面前加一個星號
- 而且這個星號可以放在任意變數
- 每個變數都分配一個元素後,剩下的元素都分配給這個帶星號的變數
# 多變數 a, b, *c, d = [1, 2, 3, 4, 5] print(a, b, c, d) # 輸出結果 1 2 [3, 4] 5
函式引數解包
主要是可變引數、關鍵字引數
詳解文章:https://www.cnblogs.com/poloyy/p/12526592.html
函式詳解文章:https://www.cnblogs.com/poloyy/p/15092393.html
解包小栗子一
# 函式 def test(a, b, c): print(a, b, c) # 正常逐個傳參 test(1, 2, 3) # 只傳一個可迭代物件,就需要解包 test(*[1, 2, 3]) test(*{1, 2, 3}) test(*(1, 2, 3)) # 輸出結果 1 2 3 1 2 3 1 2 3 1 2 3
解包小栗子二
# 函式 def test(a, b, c): print(a, b, c) # 關鍵字傳參 test(a=1, b=2, c=3) # 只傳一個可迭代物件,就需要解包,和上面寫法是等價的 test(**{"a": 1, "b": 2, "c": 3}) # 輸出結果 1 2 3 1 2 3
Python 3.5+的新特性
- 在 3.5 之前,函式呼叫時,一個函式中解包操作只允許一個 * 和一個 **
- 3.5+ 之後,可以有任意多個解包
# 函式 def test(a, b, c, d, e, f): print(a, b, c, d, e, f) test(*[1, 2, ], *[3, 4, ], **{"e": 5}, **{"f": 6}) # 輸出結果 1 2 3 4 5 6
在表示式中使用解包
栗子一
# 表示式解包 print(range(3), 3) print(*range(3), 3) print([*range(3), 3]) print({"a": 1, **{"b": 2, "c": 3}}) # 輸出結果 range(0, 3) 3 0 1 2 3 [0, 1, 2, 3] {'a': 1, 'b': 2, 'c': 3}
栗子二:拼接列表
# 解包拼接列表 list1 = [1, 2] list2 = range(3, 5) list3 = [*list1, *list2] print(list3) # 輸出結果 [1, 2, 3, 4]
list1 可以直接和 list2 做 + 操作嗎?
不行,因為 list 無法與 range() 物件相加
栗子三:拼接兩個字典
# 解包拼接字典 dict1 = {"a": 1, "b": 2} dict2 = {"name": "yy", "age": 22} dict3 = {**dict1, **dict2} print(dict3) # 輸出結果 {'a': 1, 'b': 2, 'name': 'yy', 'age': 22}
解包總結
- 自動解包支援一切可迭代物件
- 函式呼叫時,可以用 * 或者 ** 解包可迭代物件