Python - 解包的各種騷操作

小菠蘿測試筆記發表於2021-08-04

為什麼要講解包

因為我覺得解包是 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}

  

解包總結

  • 自動解包支援一切可迭代物件
  • 函式呼叫時,可以用 * 或者 ** 解包可迭代物件

 

擴充:Python 函式

https://www.cnblogs.com/poloyy/p/12526592.html

相關文章