給大家分享一篇 python有趣的解包用法
python中的解包可以這樣理解:一個list是一個整體,想把list中每個元素當成一個個個體剝離出來,這個過程就是解包,我們來看下面這些例子(分為12個部分)。
1.將list中每個元素賦值給一個變數
>>> name, age, date = ['Bob', 20, '2018-1-1']
>>> name
'Bob'
>>> age
20
>>> date
'2018-1-1'
2.可迭代物件都可以這樣做
# 列表
>>> a,b,c = ['a', 'b', 'c']
>>> a
'a'
>>> a,b,c = enumerate(['a', 'b', 'c'])
>>> a
(0, 'a')
# 元組
>>> a,b,c = ('a', 'b', 'c')
>>> a
'a'
# 字典
>>> a,b,c = {'a':1, 'b':2, 'c':3}
>>> a
'a'
>>> a,b,c = {'a':1, 'b':2, 'c':3}.items()
>>> a
('a', 1)
# 字串
>>> a,b,c = 'abc'
>>> a
'a'
# 生成器
>>> a,b,c = (x + 1 for x in range(3))
>>> a
1
如果可迭代物件包含的元素和前面待賦值變數數量不一致,則會報錯。但是可以通過*來表示多個元素
3.星號的使用
比如我們要計算平均分,去除最高分和最低分,除了用切片,還可以用解包的方式獲得中間的數值
>>> first, *new, last = [94, 85, 73, 46]
>>> new
[85, 73]
用*來表示多個數值
4.壓包過程
壓包是解包的逆過程,用zip函式實現,下面例子可以對壓包有一個直觀的感受
>>> a = ['a', 'b', 'c']
>>> b = [1, 2, 3]
>>> for i in zip(a, b):
... print(i)
...
('a', 1)
('b', 2)
('c', 3)
5.壓包與解包混合的例子
下面例子實現:兩個列表對應數值相加
>>> a = [0, 1, 2]
>>> b = [1, 2, 3]
>>> for i, j in zip(a, b):
... print(i+j)
...
1
3
5
細細拆解上面過程,可以看出步驟是這樣的
先是zip函式將a b壓包成為一個可迭代物件
對可迭代物件的每一個元素((‘a’, 1))進行解包(i, j = (‘a’, 1))
此時就可以分別呼叫i j變數進行計算
下面我們加入星號
>>> l = [('Bob', '1990-1-1', 60),
... ('Mary', '1996-1-4', 50),
... ('Nancy', '1993-3-1', 55),]
>>> for name, *args in l:
... print(name, args)
...
Bob ['1990-1-1', 60]
Mary ['1996-1-4', 50]
Nancy ['1993-3-1', 55]
6._的用法
當一些元素不用時,用_表示是更好的寫法,可以讓讀程式碼的人知道這個元素是不要的
>>> person = ('Bob', 20, 50, (11, 20, 2000))
>>> name, *_, (*_, year) = person
>>> name
'Bob'
>>> year
2000
7.多變數同時賦值
之前賦值符號右側都是可迭代物件,其實右側也可以是多個變數
>>> a, b = 1, 2
>>> a
1
>>> b
2
>>> a = 1, 2
>>> a
(1, 2)
下面用法都會報錯
*a = 1, 2
a, b, c = 1, 2
可以這樣
*a, = 1, 2
8.*之可變引數
函式定義時,我們使用*的可變引數,其實也是壓包解包過程
>>> def myfun(*num):
... print(num)
...
>>> myfun(1,2,5,6)
(1, 2, 5, 6)
引數用*num表示,num變數就可以當成元組呼叫了。
其實這個過程相當於*num, = 1,2,5,6
9.*之關鍵字引數
>>> def myfun(**kw):
... print(kw)
...
>>> myfun(name = "Bob", age = 20, weight = 50)
{'weight': 50, 'name': 'Bob', 'age': 20}
鍵值對傳入**kw,kw就可以表示相應字典。
**的用法只在函式定義中使用,不能這樣使用
a, **b = {'weight': 50, 'name': 'Bob', 'age': 20}
10.可變引數與關鍵字引數的細節問題
(1)函式傳入實參時,可變引數(*)之前的引數不能指定引數名
>>> def myfun(a, *b):
... print(a)
... print(b)
...
>>> myfun(a=1, 2,3,4)
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>> myfun(1, 2,3,4)
1
(2, 3, 4)
(2)函式傳入實參時,可變引數(*)之後的引數必須指定引數名,否則就會被歸到可變引數之中
>>> def myfun(a, *b, c=None):
... print(a)
... print(b)
... print(c)
...
>>> myfun(1, 2,3,4)
1
(2, 3, 4)
None
>>> myfun(1, 2,3,c=4)
1
(2, 3)
4
如果一個函式想要使用時必須明確指定引數名,可以將所有引數都放在可變引數之後,而可變引數不用管它就可以,也不用命名,如下
>>> def myfun(*, a, b):
... print(a)
... print(b)
...
>>> myfun(a = 1,b = 2)
1
2
可變引數的這兩條特性,可以用於將 只需要按照位置賦值的引數 和 需要明確指定引數名的引數區分開來
(3)關鍵字引數都只能作為最後一個引數,前面的引數按照位置賦值還是名稱賦值都可以
下面展示一個既用可變引數有用關鍵字引數的例子
>>> def myfun(a, *b, c, **d):
... print(a)
... print(b)
... print(c)
... print(d)
...
>>> myfun(1, 2, 3, c= 4, m = 5, n = 6)
1
(2, 3)
4
{'n': 6, 'm': 5}
(4)可變引數與關鍵詞引數共同使用以表示任意引數
下面是這一點在裝飾器當中的使用
>>> def mydecorator(func):
... def wrapper(*args, **kw):
... print('I am using a decorator.')
... return func(*args, **kw)
... return wrapper
...
>>> @mydecorator
... def myfun(a, b):
... print(a)
... print(b)
...
>>> myfun(1, b = 2)
I am using a decorator.
1
2
(如果有的讀者不熟悉裝飾器,只需要知道,使用@定義myfun相當於myfun = mydecorator(myfun),定義出來的myfun其實是返回結果wrapper函式)
wrapper函式使用*args, **kw作為引數,則被修飾的myfun函式需要的引數無論是什麼樣的,傳入wrapper都不會報錯,這保證了裝飾器可以修飾各種各樣函式的靈活性。畢竟我們一般在函式中傳入引數時,要麼所有引數名都寫,要麼前面幾個不寫,後面的會寫,這樣使用*args, **kw完全沒有問題。
11.解包作為引數傳入函式中
首先定義一個函式
def myfun(a, b):
print(a + b)
列表元組的解包
>>> n = [1, 2]
>>> myfun(*n)
3
>>> m = (1, 2)
>>> myfun(*m)
3
字典的解包
>>> mydict = {'a':1, 'b': 2}
>>> myfun(**mydict)
3
>>> myfun(*mydict)
ba
一個應用
>>> bob = {'name': 'Bob', 'age': 30}
>>> "{name}'s age is {age}".format(**bob)
"Bob's age is 30"
12.多返回值函式
下面過程也涉及到了解包
def myfun(a, b):
return a + 1, b + 2
>>> m, n = myfun(1, 2)
>>> m
2
>>> n
4
其實本身是一個元組
>>> p = myfun(1, 2)
>>> p
(2, 4)
Python學習交流群:834179111,群裡有很多的學習資料。歡迎歡迎各位前來交流學習。