python有趣的解包用法
python中的解包可以這樣理解:一個list是一個整體,想把list中每個元素當成一個個個體剝離出來,這個過程就是解包,我們來看下面這些例子(分為12個部分)。
1.將list中每個元素賦值給一個變數
>>> name, age, date = [Bob, 20, 2018-1-1]>>> nameBob>>> age20>>> date2018-1-1
2.可迭代對象都可以這樣做
# 列表>>> a,b,c = [a, b, c]>>> aa>>> a,b,c = enumerate([a, b, c])>>> a(0, a)# 元組>>> a,b,c = (a, b, c)>>> aa# 字典>>> a,b,c = {a:1, b:2, c:3}>>> aa>>> a,b,c = {a:1, b:2, c:3}.items()>>> a(a, 1)# 字元串>>> a,b,c = abc>>> aa# 生成器>>> a,b,c = (x + 1 for x in range(3))>>> a1
如果可迭代對象包含的元素和前面待賦值變數數量不一致,則會報錯。但是可以通過*
來表示多個元素
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)...135
細細拆解上面過程,可以看出步驟是這樣的
- 先是
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>>> nameBob>>> year2000
7.多變數同時賦值
之前賦值符號右側都是可迭代對象,其實右側也可以是多個變數
>>> a, b = 1, 2>>> a1>>> b2>>> a = 1, 2>>> a(1, 2)
下面用法都會報錯
*a = 1, 2a, 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 1SyntaxError: 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)12
可變參數的這兩條特性,可以用於將 只需要按照位置賦值的參數 和 需要明確指定參數名的參數區分開來
(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.12
(如果有的讀者不熟悉裝飾器,只需要知道,使用@
定義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)"Bobs age is 30"
12.多返回值函數
下面過程也涉及到了解包
def myfun(a, b): return a + 1, b + 2>>> m, n = myfun(1, 2)>>> m2>>> n4
其實本身是一個元組
>>> p = myfun(1, 2)>>> p(2, 4)
專欄信息
專欄主頁:python編程
專欄目錄:目錄
版本說明:軟體及包版本說明
推薦閱讀: