正確理解python ** 雙星 和 * 單星

如果我們經常看一些python包的原始的代碼,經常會發現 他們定義的方法會在最後參數列表位置 包含 *args 或者 **kwargs, 這樣的書寫可以增加方法的健壯性,除了必須要的參數和默認參數,多餘的參數再多也不會報錯,,那我們還是 需要理解一下 ** *

單星 *
1.一般用在 元組 tuple 和list 列表,加上* 以後等於給他 加上了 位置屬性, 類似索引
舉例

def foo(a,b):
    print(a+b)
pos_list=(3,54)

pai_list=(3,54,21,34)
foo(*pos_list)

本來 函數 foo 需要兩個參數 a 和b ,剛好你有 兩個列表pos_list 有兩個元素,pai_list有四個元素,
如果你直接 foo(pos_list) 是報錯的,foo 需要的是兩個參數,而且根據函數體,我們可以判斷需要的是數字類型的變量,你傳入一個列表就當然報錯了,
怎麼辦,把列表的元素取出來呢
最簡單就是這樣,把列表的元素按索引取出來
foo( pos_list[0], pos_list[1]),這個是可以正常執行的,不過未免有點低效,
有沒有辦法 直接把 pos_list[0]映射給參數a, pos_list[1]映射給參數b ?

當然有 就是 列表前加星號* ,有點像c語言取地址符 ,這樣列表 其實就帶了position屬性
只要列表的元素個數和 參數個數相等,就可以一一對應。
foo(*pos_list) 可以正常執行

那如果 列表元素個數超過 參數個數,直接加星號就會報給的參數過多的錯誤, 不過我們可以使用切片 的方法來解決

def foo(a,b):
    print(a+b)

pai_list=(3,54,21,34)
foo(*pai_list[0:2])

2.單星也會用在循環中,比如 合併兩個或者多個list

pos_list=(3,54)

pai_list=(3,54,21,34)

res_list=[  *pos_list,*pai_list]
print(res_list)
>>  [3, 54, 21, 34, 3, 54]

tuple_res=(*lis,*lisz)
print(tuple_res)
>> (3, 54, 21, 34, 3, 54)

雙星 **
1.雙星 主要是應用在鍵值對上,一般就是字典dict ,加兩個星 這個其實就是把字典的key 映射爲函數參數名,value 映射爲參數值,這裏有一個條件,就是 key 要和參數名 對應上, 否則會報錯,而且 數據類型也要保證是對應的

def foo(a,b):
    print(a+b)

dic={'a':56,'b':45}
foo(**dic)

2.雙星 會應用到循環上 會是 非常高效和優雅的方式
比如你打算合併兩個 字典 dict_1 dict_2

dic_1={'a':56,'b':45}
dic_2={'c':26,'d':15}
dic_res={ **dic_1,**dic_2}

print(dic_res)
>>
{'a': 56, 'c': 26, 'b': 45, 'd': 15}

需要注意的是如果兩個字典出現重複key 的話,有一個會被覆蓋掉
基於這種方式 你甚至可以一口氣合併七八個字典

dic_1={'a':56,'b':45}
dic_2={'c':26,'d':15}
dic_3={'e':26,'r':15}
dic_res={ **dic_1,**dic_2,**dic_3}

print(dic_res)
>> {'e': 26, 'd': 15, 'r': 15, 'a': 56, 'b': 45, 'c': 26}

3 在函數聲明中看到 參數 單星和雙星 含義就是 單星意味着 接受不定參數,並且把這些不定參數當做tuple來處理,雙星參數則意味着 接受不定參數的鍵值對,並且把鍵映射爲參數名,值映射爲參數值 或者說 如果你輸入了 多個參數及值,則會把他映射成字典dict


def foo(*t):
    print(t)

>>> foo(1, 2)
(1, 2)

def foo(**d):
    print(d)

>>> foo(x=1, y=2)
{'y': 2, 'x': 1}

dic_1={'a':56,'b':45}
foo(**dic_1)
>>{'a':56,'b':45} 

另外 * 作爲列表的不定參數子集存在

>>> x, *xs = (1, 2, 3, 4)
>>> x
1
>>> xs
[2, 3, 4]

>>> *xs, x = (1, 2, 3, 4)
>>> xs
[1, 2, 3]
>>> x
4

>>> x, *xs, y = (1, 2, 3, 4)
>>> x
1
>>> xs
[2, 3]
>>> y
4

>>> for (x, *y, z) in [ (1, 2, 3, 4) ]: print(x, y, z)
...
1 [2, 3] 4

參考

In a function call
*t means "treat the elements of this tuple as positional arguments to this function call."

def foo(x, y):
    print(x, y)

>>> t = (1, 2)
>>> foo(*t)
1 2
Since v3.5, you can also do this in a list/tuple/set literals:

>>> [1, *(2, 3), 4]
[1, 2, 3, 4]
**d means "treat the key-value pairs in the dictionary as additional named arguments to this function call."

def foo(x, y):
    print(x, y)

>>> d = {'x':1, 'y':2}
>>> foo(**d)
1 2
Since v3.5, you can also do this in a dictionary literals:

>>> d = {'a': 1}
>>> {'b': 2, **d}
{'b': 2, 'a': 1}
In a function signature
*t means "take all additional positional arguments to this function and pack them into this parameter as a tuple."

def foo(*t):
    print(t)

>>> foo(1, 2)
(1, 2)
**d means "take all additional named arguments to this function and insert them into this parameter as dictionary entries."

def foo(**d):
    print(d)

>>> foo(x=1, y=2)
{'y': 2, 'x': 1}
In assignments and for loops
*x means "consume additional elements in the right hand side", but it doesn't have to be the last item. Note that x will always be a list:

>>> x, *xs = (1, 2, 3, 4)
>>> x
1
>>> xs
[2, 3, 4]

>>> *xs, x = (1, 2, 3, 4)
>>> xs
[1, 2, 3]
>>> x
4

>>> x, *xs, y = (1, 2, 3, 4)
>>> x
1
>>> xs
[2, 3]
>>> y
4

>>> for (x, *y, z) in [ (1, 2, 3, 4) ]: print(x, y, z)
...
1 [2, 3] 4

https://stackoverflow.com/questions/21809112/what-does-tuple-and-dict-means-in-python

https://python-reference.readthedocs.io/en/latest/docs/operators/dict_unpack.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章