# 理解’*’,’*args’,’**’,’**kwargs’

``````>>> l = [7,4]
>>> fun(*l)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() takes exactly 3 arguments (2 given)``````
• 1
• 2
• 3
• 4
• 5
• 1
• 2
• 3
• 4
• 5

‘*l’與位置引數混合使用

``````>>> fun(23, *l)
23 7 4``````
• 1
• 2
• 1
• 2

## 通過一個函式的定義來理解’*args’的含義

``````>>> def fun(*args):
...     print args
... ``````
• 1
• 2
• 3
• 1
• 2
• 3

``````>>> fun(13)
(13,)``````
• 1
• 2
• 1
• 2

``````>>> fun(11,93,43)
(11, 93, 43)``````
• 1
• 2
• 1
• 2

### ‘*args’在函式定義中是做什麼用的？

``````>>> def fun(a, *args):
...     print "a is ", a
...     print "args is ", args
... ``````
• 1
• 2
• 3
• 4
• 1
• 2
• 3
• 4

``````>>> fun(11,12,34,43)
a is  11
args is  (12, 34, 43)``````
• 1
• 2
• 3
• 1
• 2
• 3

``````>>> fun(91)
a is  91
args is  ()``````
• 1
• 2
• 3
• 1
• 2
• 3

``````>>> def fun(a, *args):
...     print a
...     print "args can receive a tuple of any number of arguments, let's print all that."
...     for arg in args:
...             print arg
... ``````
• 1
• 2
• 3
• 4
• 5
• 6
• 1
• 2
• 3
• 4
• 5
• 6

``````>>> fun(1,5,6,7)
1
args can receive a tuple of any number of arguments, let's print all that.
5
6
7``````
• 1
• 2
• 3
• 4
• 5
• 6
• 1
• 2
• 3
• 4
• 5
• 6

‘args’既然是元組，我們就可以遍歷它。

``````>>> def calculate_sum(*args):
...     return sum(args)
... ``````
• 1
• 2
• 3
• 1
• 2
• 3

``````>>> def ignore_first_calculate_sum(a,*iargs):
...     required_sum = calculate_sum(*iargs)
...     print "sum is ", required_sum
... ``````
• 1
• 2
• 3
• 4
• 1
• 2
• 3
• 4

‘required_sum=calculate_sum(iargs)’不能這麼呼叫，因為傳給’calculate_sum’之前我們需要unpack數值。不使用’*’將不會unpack數值,也就不能執行想要的動作。呼叫函式如下:

``````>>> ignore_first_calculate_sum(12, 1,4,5)
sum is  10
>>> ignore_first_calculate_sum()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ignore_first_calculate_sum() takes at least 1 argument (0 given)``````
• 1
• 2
• 3
• 4
• 5
• 6
• 1
• 2
• 3
• 4
• 5
• 6

## 通過一個函式的呼叫來理解’**’的作用

``````>>> def fun(a, b, c):
...     print a, b, c
...
>>> fun(1,5,7)
1 5 7
>>> fun(a=1,b=5,c=7)
1 5 7``````
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 1
• 2
• 3
• 4
• 5
• 6
• 7

``````>>> d={'b':5, 'c':7}
>>> fun(1, **d)
1 5 7``````
• 1
• 2
• 3
• 1
• 2
• 3

### 在函式呼叫中”**”做了什麼？

``````>>> d = {'c':3}
>>> fun(1, 4, **d)
1 4 3
>>> d = {'a':7, 'b':3, 'c':8}
>>> fun(**d)
7 3 8``````
• 1
• 2
• 3
• 4
• 5
• 6
• 1
• 2
• 3
• 4
• 5
• 6

``````>>> d = {'a':7, 'b':3, 'c':8, 'd':90}
>>> fun(**d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() got an unexpected keyword argument 'd'``````
• 1
• 2
• 3
• 4
• 5
• 1
• 2
• 3
• 4
• 5

``````>>> d = {'a':7, 'b':3,'d':90}
>>> fun(**d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() got an unexpected keyword argument 'd'``````
• 1
• 2
• 3
• 4
• 5
• 1
• 2
• 3
• 4
• 5

fun(**d)等同於fun(a=7, b=3, d=90).傳給函式”fun”想要的引數個數，但引數列表中並沒有’d’,呼叫中’d’鍵值引數傳給函式導致TypeError.

So, “*” unpacks the dictionary i.e the key values pairs in the dictionary as keyword arguments and these are sent as keyword arguments to the function being called. “” unpacks a list/tuple i.e the values in the list as positional arguments
and these are sent as positional arguments to the function being called.

## 通過函式定義來理解’**kwargs’的含義

``````>>> def fun(a, **kwargs):
...     print a, kwargs
... ``````
• 1
• 2
• 3
• 1
• 2
• 3

``````>>> fun(1, b=4, c=5)
1 {'c': 5, 'b': 4}
>>> fun(45, b=6, c=7, d=8)
45 {'c': 7, 'b': 6, 'd': 8}``````
• 1
• 2
• 3
• 4
• 1
• 2
• 3
• 4

``````>>> def fun(a, **kwargs):
...     print "a is ", a
...     print "We expect kwargs 'b' and 'c' in this function"
...     print "b is ", kwargs['b']
...     print "c is ", kwargs['c']
...
>>> fun(1, b=3,c=5)
a is  1
We expect kwargs 'b' and 'c' in this function
b is  3
c is  5``````
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11

``````>>> fun(1, b=3, d=5)
a is  1
We expect kwargs 'b' and 'c' in this function
b is  3
c is
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in fun
KeyError: 'c'``````
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9

``````>>> fun(1, b=3, d=5, c=9)
a is  1
We expect kwargs 'b' and 'c' in this function
b is  3
c is  9``````
• 1
• 2
• 3
• 4
• 5
• 1
• 2
• 3
• 4
• 5

``````>>> fun(1, {'b':2, 'c':34})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() takes exactly 1 argument (2 given)``````
• 1
• 2
• 3
• 4
• 1
• 2
• 3
• 4

``````>>> fun(1, **{'b':2, 'c':34})
a is  1
We expect kwargs 'b' and 'c' in this function
b is  2
c is  34``````
• 1
• 2
• 3
• 4
• 5
• 1
• 2
• 3
• 4
• 5

## 通過一個應用例項來說明’args’,’kwargs’應用場景以及為何要使用它

``````>>> class Model(object):
...     def __init__(self, name):
...             self.name = name
...     def save(self, force_update=False, force_insert=False):
...             if force_update and force_insert:
...                     raise ValueError("Cannot perform both operations")
...             if force_update:
...                     print "Updated an existing record"
...             if force_insert:
...                     print "Created a new record"
... ``````
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 8
• 9
• 10
• 11

``````>>> class Child(Model):
...     def save(self, *args, **kwargs):
...             if self.name=='abcd':
...                     super(ChildModel, self).save(*args, **kwargs)
...             else:
...                     return None
... ``````
• 1
• 2
• 3
• 4
• 5
• 6
• 7
• 1
• 2
• 3
• 4
• 5
• 6
• 7

``````>>> c=ChildModel('abcd')
>>> c.save(force_insert=True)
Created a new record
>>> c.save(force_update=True)
Updated an existing record``````
• 1
• 2
• 3
• 4
• 5
• 1
• 2
• 3
• 4
• 5

‘force_insert’ and acted accordingly.