1. 程式人生 > >Python中 * 和 ** 的打包和解包

Python中 * 和 ** 的打包和解包

python中的 * 和 ** ,能夠讓函式支援任意數量的引數,它們在函式定義和呼叫中,有著不同的目的。

一、打包引數

* 的作用:在函式定義中,收集所有位置引數到一個新的元組,並將整個元組賦值給變數args。

def f(*args):
    print(args)


f()  # ()
f(1)  # (1,)
f(1,2,3,4,5)  #(1,2,3,4,5)

** 的作用:在函式定義中,收集關鍵字引數到一個新的字典,並將整個字典賦值給變數kwargs。

def f(**kwargs):
    print(kwargs)

f()     # {}
f(a=1, b=2)     # {'a': 1, 'b': 2}

二、解包引數

* 的作用:在函式呼叫中,* 能夠將元組或列表解包成不同的引數。

def func(a, b, c, d):
    print(a, b, c, d)


argc = (1, 2, 3, 4)
func(*argc)     # 1 2 3 4

argc = [1, 2, 3, 4]
func(*argc)     # 1 2 3 4

** 的作用:在函式呼叫中,** 會以鍵/值的形式解包一個字典,使其成為一個獨立的關鍵字引數。

def func(a,b,c,d):
    print(a,b,c,d)

kwargs = {'a':1, 'b':2, 'c':3, 'd':4}
func(**kwargs)      # 1 2 3 4

三、注意

1、在函式定義時, * 表示打包,在函式體內部, * 表示的卻是解包,事實上,下面例子中print(*args)是print()函式的呼叫。

def foo(*args, **kwargs):
    print(args)  # 未解包引數
    print(*args)  # 解包引數


v = (1, 2, 4)
d = {'a': 1, 'b': 12}
foo(v, d)

#   ((1, 2, 4), {'a': 1, 'b': 12})
#   (1, 2, 4) {'a': 1, 'b': 12}

2. 打包和解包並不能脫離函式而存在

表面上看並沒有什麼函式,實際上是有的,用的就是format的函式呼叫

c = {'name':'張', 'age':12}

**c  # 報錯資訊: SyntaxError: invalid syntax

print("Name:{name}, Age:{age}".format(**c))   # Name:張, Age:12

參考原始碼中對format函式的定義

但是這個字典解包不能用print函式輸出

print(**c)
Traceback (most recent call last):
  File "<pyshell#40>", line 1, in <module>
    print(**c)
TypeError: 'age' is an invalid keyword argument for this function

因為上述字典解出來的形式是這樣的:

**c = name='zhang',age=2

而print函式只支援*args,不支援**kwargs

 

3. 在ddt中的應用

@ddt.data(*all_caseDatas)中,data是一個函式,呼叫函式的時候,引數*all_caseDatas自動將引數列表[{}, {}, {}...]解包為{},{},{}...,在def data(*values)函式中,*會自動將各個位置引數打包成新的元組({}, {}, {}...),然後@ddt.data就可以獲取每一條資料作為測試用例了

@ddt.data(*all_caseDatas)
    def test_my_request(self, case_data):
        global global_var
        if len(global_var) != 0 and case_data["request_data"] is not None:
            for key, value in global_var.items():
                if case_data["request_data"].find(key) != -1:
                    case_data["request_data"] = case_data["request_data"].replace(key, value)

四、練習

def f(str1, *args, **kwargs):
    print(str1, args, kwargs)

l = [1, 2, 3]
t = [4, 5, 6]
d = {"a":7, "b":8, "c":9}

f(1, 2)
f(1, 2, 3, "python")
f("python", a=1, b=2, c=3)

print("================")

f("python", l, d)
f("python", *t)
f("python", *l, **d)
f("python", q="winning", **d)


執行結果:
(2,) {}
(2, 3, 'python') {}
python () {'a': 1, 'b': 2, 'c': 3}
================
python ([1, 2, 3], {'a': 7, 'b': 8, 'c': 9}) {}
python (4, 5, 6) {}
python (1, 2, 3) {'a': 7, 'b': 8, 'c': 9}
python () {'a': 7, 'b': 8, 'q': 'winning', 'c': 9}

需要注意的是f("python", *t)是把列表t先解包成 4, 5, 6,然後在def f(str1, *args, **kwargs):中將4, 5, 6重新打包成新的元組(4, 5, 6)再傳遞給變數args