小議Python中自定義函數的可變參數的使用及注意點
可變參數
Python的可變參數有兩種,一種是列表類型,一種是字典類型。列表類型類似 C 中的可變參數,定義方式為
def test_list_param(*args) :
for arg in args :
print arg
其中 args 是一個 tuple。
字典類型的可變參數:
def test_dict_param(**args) :
for k, v in args.iteritems() :
print k, v
其中 args 是一個 dictionary
可以分別傳遞 tuple 和 dictionary 給相應的可變參數,格式如下
a = (1, 2, 3)
b = {"a":1, "b":2, "msg":"hello"}
test_list_param(*a)
test_dict_param(**b)
帶默認參數的函數
函數的帶默認值參數能夠很大程度上方便我們使用:一般情況下可以省略傳參使用參數的默認值,也可以主動傳參;調用的時候也不用在意參數的順序方便使用,并且直接、顯式;甚至還能用來當作魔法值,做一些邏輯上的控制。
但是由于python的默認值參數只會在函數定義處被解析一次,此后每次調用函數的時候,默認值參數都會是這個值了。碰到一些不可變的數據類型比如:整型,字符串,元祖之類的還好,但如果碰到可變類型的數據比如數組的話,就會有發(fā)生一些意想不到的事情。
讓我們舉一個簡單的例子說明一下:
def add_to(num, target=[]): target.append(num) print id(target), target add_to(1) # Output: 39003656, [1] add_to(2) # Output: 39003656, [1, 2] add_to(3) # Output: 39003656, [1, 2, 3]
很顯然如果你是想每次調用函數都能得到一個新的包含期望結果的數組,肯定不能如愿了。函數add_to的參數target在函數第一次被解析的時候會被賦值成空的數組,因為只會被解析一次,以后每次調用的時候都會在這個target變量的基礎上進行操作,變量的id值也完全一樣。想要得到預期的結果,可以為這種可變數據類型的參數指定一個None來表示空值:
a = (1, 2, 3)
b = {"a":1, "b":2, "msg":"hello"}
test_list_param(*a)
test_dict_param(**b)
在python的世界里,參數是按標識符傳遞(粗暴點解釋就是按引用傳遞的),你需要擔心的是參數的類型是否是可變的:
>>> def test(param1, param2): ... print id(param1), id(param2) ... param1 += 1 ... param2 += 1 ... print id(param1), id(param2) ... >>> var1 = 1 >>> var2 = 2 >>> print id(var1), id(var2) 36862728 36862704 >>> test(var1, var2) 36862728 36862704 36862704 36862680
可變的數據類型,函數局部作用域里面的任何改變會保留在數據上;不可變的數據類型,發(fā)生的任何改變都只會體現在新生成的局部變量上,如同上面的列子中所示的效果,讀者可以對比一下。

