parameter跟argument的差異
基本上這兩者是一樣的,不過使用在不同的情境下。如果混用了其實是沒關係,可能也沒人會在意
不過值得一提的是以上這個範例的兩個參數在Module Scope
跟Function Scope
中都是指向同一個記憶體位置
可迭代物件的拆解機制(unpacking)
可迭代的物件都能拆解,很適合用在參數傳遞(主要使用在有序物件上)
1 2 3 4 5 6 |
a, b = ['A', 'B'] # list a, b = 'A', 'B' # tuple a, b = 'AB' # str a, b = {'A', 'B'} # set 注意這裡會有兩種結果 a, b = {'A': 10, 'B': 20} # dict 注意這裡會有兩種結果 |
超簡單實現swap
傳統的作法
1 2 3 4 5 6 7 |
a = 10 b = 20 tep = a a = b b = temp |
unpacking的作法
1 2 3 4 |
a = 10 b = 20 a, b = b, a |
使用*
和**
(3.5以上適用)
1 2 3 |
*a = 'python' a, *b, c = 1, 2, 3, 4 |
1 2 3 4 |
l1 = [1, 2, 3] l2 = 'XYZ' l = [*l1, *l2] |
1 2 3 4 5 |
s1 = {1, 2, 3} s2 = {4} # merge set s = {*s1, *s2} |
1 2 3 4 5 6 7 |
d1 = {'a': 1, 'b': 2} d2 = {'c': 3} d3 = {'a': 0} # merge dictionary d = {**d1, **d2, **d3} # 注意這裡a的值會被覆寫 d = {**d1, a: 0} # 注意這裡a的值會被覆寫 |
unpacking範例
巢狀的unpacking
1 2 3 4 |
a, b, (c, d) = [1, 2, [3, 4]] a, *b, (c, d, e) = [1, 2, 3, 'XYZ'] a, *b, (c, *d) = [1, 2, 3, 'python'] # a=1, b=[2, 3], c='p', d=['y', 't', 'h', 'o', 'n'] |
使用unpacking來處理parameters
規則:
- 關鍵字參數(keyword argument)後方不能再接位置參數(positional arguments)
- 你不能在
*args
的後方再使用位置參數 - 你不能在
**kwargs
的後方再傳入任何參數
*args
用tuple收集所有或剩下的
1 2 3 4 5 |
def my_func(a, b, *args): # your code here l = [1, 2, 3, 4] my_func(*l) # a=1, b=2, args=[3, 4] |
這裡要注意的是,你不能在*args
的後方再使用位置參數,因為*args
後面再傳入的會被視作keyword arguments
1 2 3 4 5 6 |
def func(a, b, *args, d): # code here func(1, 2, 'x', 'y', d) # 這樣是不行的,沒有指名keyword arguments func(1, 2) # 這樣是不行的,沒有指名keyword arguments func(1, 2, 'x', 'y', d=100) # 這樣是可以的 |
我們一樣可以不要強制傳入位置參數:
1 2 3 |
def func(*args, d): # code here |
或者可以強制不要傳入位置參數:
1 2 3 |
def func(*, d): # code here |
再舉個例子
1 2 3 4 5 |
def func(a, b=1, *, d, e=True): # 最多只能傳a, b這2個位置參數,另外強制傳入關鍵字參數d # code here def func(a, b=1, *args, d, e=True, f): # 最少要傳a這個位置參數,另外強制傳入關鍵字參數d, f # code here |
*kwargs
以dictionary收集所有或剩下的keyword arguments,注意:你不能在**kwargs
的後方再傳入任何參數
應用範例
Python的print,把arguments用objects變數收集,並在後面額外定義4個帶有預設值的keyword argumemts
1 2 |
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) |
用keyword arguments來設定方法的行為
1 2 3 4 5 6 7 8 |
def get_avg(*args, log=False): hi = max(args) if len(args) > 0 else 0 lo = min(args) if len(args) > 0 else 0 avg = (hi+lo)/2 if log: print('hi={}, lo={}, avg={}'.format(hi, lo, avg)) return avg |
設定參數的預設值(Default Values)應該注意的事情
我們先來討論function在被import的時候發生了什麼事情:
1. import的程式會馬上被執行
2. 函式、該函式的參數預設值在執行當下陸續被新增並儲存到記憶體中
3. 當函式後續被呼叫(call, invoke)的時候,執行該函式
有的情況下你會想要在函式建立的當下初始化參數,也就是上面第2步說明的:
有時候你的用意並非如此,你可能想要函式被呼叫的當下初始化參數,也就是上面第3步說明的:
另外要注意的是使用可變序列當預設值會遇到以下情況: