學(xué)習(xí) python有趣的解包用法

python中的解包可以這樣理解:一個(gè)list是一個(gè)整體,想把list中每個(gè)元素當(dāng)成一個(gè)個(gè)個(gè)體剝離出來,這個(gè)過程就是解包,我們來看下面這些例子(分為12個(gè)部分)。

1.將list中每個(gè)元素賦值給一個(gè)變量

>>> 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

如果可迭代對象包含的元素和前面待賦值變量數(shù)量不一致,則會(huì)報(bào)錯(cuò)。但是可以通過*來表示多個(gè)元素

3.星號(hào)的使用

比如我們要計(jì)算平均分,去除最高分和最低分,除了用切片,還可以用解包的方式獲得中間的數(shù)值

>>> first, *new, last = [94, 85, 73, 46]
>>> new
[85, 73]

用*來表示多個(gè)數(shù)值

4.壓包過程

壓包是解包的逆過程,用zip函數(shù)實(shí)現(xiàn),下面例子可以對壓包有一個(gè)直觀的感受

>>> a = ['a', 'b', 'c']
>>> b = [1, 2, 3]
>>> for i in zip(a, b):
...     print(i)
...
('a', 1)
('b', 2)
('c', 3)

5.壓包與解包混合的例子

下面例子實(shí)現(xiàn):兩個(gè)列表對應(yīng)數(shù)值相加

>>> a = [0, 1, 2]
>>> b = [1, 2, 3]
>>> for i, j in zip(a, b):
...     print(i+j)
...
1
3
5

細(xì)細(xì)拆解上面過程,可以看出步驟是這樣的

先是zip函數(shù)將a b壓包成為一個(gè)可迭代對象
對可迭代對象的每一個(gè)元素(('a', 1))進(jìn)行解包(i, j = ('a', 1))
此時(shí)就可以分別調(diào)用i j變量進(jìn)行計(jì)算
下面我們加入星號(hào)

>>> 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._的用法

當(dāng)一些元素不用時(shí),用_表示是更好的寫法,可以讓讀代碼的人知道這個(gè)元素是不要的

>>> person = ('Bob', 20, 50, (11, 20, 2000))
>>> name, *_, (*_, year) = person
>>> name
'Bob'
>>> year
2000

7.多變量同時(shí)賦值

之前賦值符號(hào)右側(cè)都是可迭代對象,其實(shí)右側(cè)也可以是多個(gè)變量

>>> a, b = 1, 2
>>> a
1
>>> b
2
>>> a = 1, 2
>>> a

(1, 2)
下面用法都會(huì)報(bào)錯(cuò)

*a = 1, 2
a, b, c = 1, 2

可以這樣

*a, = 1, 2

8.*之可變參數(shù)

函數(shù)定義時(shí),我們使用*的可變參數(shù),其實(shí)也是壓包解包過程

>>> def myfun(*num):
...     print(num)
...
>>> myfun(1,2,5,6)
(1, 2, 5, 6)

參數(shù)用*num表示,num變量就可以當(dāng)成元組調(diào)用了。

其實(shí)這個(gè)過程相當(dāng)于*num, = 1,2,5,6

9.*之關(guān)鍵字參數(shù)

>>> def myfun(**kw):
...     print(kw)
...
>>> myfun(name = "Bob", age = 20, weight = 50)
{'weight': 50, 'name': 'Bob', 'age': 20}

鍵值對傳入**kw,kw就可以表示相應(yīng)字典。

**的用法只在函數(shù)定義中使用,不能這樣使用

a, **b = {'weight': 50, 'name': 'Bob', 'age': 20}

10.可變參數(shù)與關(guān)鍵字參數(shù)的細(xì)節(jié)問題

(1)函數(shù)傳入實(shí)參時(shí),可變參數(shù)(*)之前的參數(shù)不能指定參數(shù)名

>>> 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)函數(shù)傳入實(shí)參時(shí),可變參數(shù)(*)之后的參數(shù)必須指定參數(shù)名,否則就會(huì)被歸到可變參數(shù)之中

>>> 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

如果一個(gè)函數(shù)想要使用時(shí)必須明確指定參數(shù)名,可以將所有參數(shù)都放在可變參數(shù)之后,而可變參數(shù)不用管它就可以,也不用命名,如下

>>> def myfun(*, a, b):
...     print(a)
...     print(b)
...
>>> myfun(a = 1,b = 2)
1
2

可變參數(shù)的這兩條特性,可以用于將 只需要按照位置賦值的參數(shù) 和 需要明確指定參數(shù)名的參數(shù)區(qū)分開來

(3)關(guān)鍵字參數(shù)都只能作為最后一個(gè)參數(shù),前面的參數(shù)按照位置賦值還是名稱賦值都可以

下面展示一個(gè)既用可變參數(shù)有用關(guān)鍵字參數(shù)的例子

>>> 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)可變參數(shù)與關(guān)鍵詞參數(shù)共同使用以表示任意參數(shù)

下面是這一點(diǎn)在裝飾器當(dāng)中的使用

>>> 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相當(dāng)于myfun = mydecorator(myfun),定義出來的myfun其實(shí)是返回結(jié)果wrapper函數(shù))

wrapper函數(shù)使用*args, *kw作為參數(shù),則被修飾的myfun函數(shù)需要的參數(shù)無論是什么樣的,傳入wrapper都不會(huì)報(bào)錯(cuò),這保證了裝飾器可以修飾各種各樣函數(shù)的靈活性。畢竟我們一般在函數(shù)中傳入?yún)?shù)時(shí),要么所有參數(shù)名都寫,要么前面幾個(gè)不寫,后面的會(huì)寫,這樣使用args, **kw完全沒有問題。

11.解包作為參數(shù)傳入函數(shù)中

首先定義一個(gè)函數(shù)

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

一個(gè)應(yīng)用

>>> bob = {'name': 'Bob', 'age': 30}
>>> "{name}'s age is {age}".format(**bob)
"Bob's age is 30"

12.多返回值函數(shù)

下面過程也涉及到了解包

def myfun(a, b):
    return a + 1, b + 2
>>> m, n = myfun(1, 2)
>>> m
2
>>> n
4

其實(shí)本身是一個(gè)元組

>>> p = myfun(1, 2)
>>> p
(2, 4)

Python學(xué)習(xí)交流群:834179111,群里有很多的學(xué)習(xí)資料。歡迎歡迎各位前來交流學(xué)習(xí)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容