Python的可變參數(shù)有兩種,一種是列表類型,一種是字典類型。列表類型類似 C 中的可變參數(shù),定義方式為
1
2
3
|
def test_list_param( * args) : for arg in args : print arg |
其中 args 是一個(gè) tuple。
字典類型的可變參數(shù):
1
2
3
|
def test_dict_param( * * args) : for k, v in args.iteritems() : print k, v |
其中 args 是一個(gè) dictionary
可以分別傳遞 tuple 和 dictionary 給相應(yīng)的可變參數(shù),格式如下
1
2
3
4
|
a = ( 1 , 2 , 3 ) b = { "a" : 1 , "b" : 2 , "msg" : "hello" } test_list_param( * a) test_dict_param( * * b) |
帶默認(rèn)參數(shù)的函數(shù)
函數(shù)的帶默認(rèn)值參數(shù)能夠很大程度上方便我們使用:一般情況下可以省略傳參使用參數(shù)的默認(rèn)值,也可以主動(dòng)傳參;調(diào)用的時(shí)候也不用在意參數(shù)的順序方便使用,并且直接、顯式;甚至還能用來當(dāng)作魔法值,做一些邏輯上的控制。
但是由于python的默認(rèn)值參數(shù)只會(huì)在函數(shù)定義處被解析一次,此后每次調(diào)用函數(shù)的時(shí)候,默認(rèn)值參數(shù)都會(huì)是這個(gè)值了。碰到一些不可變的數(shù)據(jù)類型比如:整型,字符串,元祖之類的還好,但如果碰到可變類型的數(shù)據(jù)比如數(shù)組的話,就會(huì)有發(fā)生一些意想不到的事情。
讓我們舉一個(gè)簡單的例子說明一下:
1
2
3
4
5
6
7
8
9
10
|
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] |
很顯然如果你是想每次調(diào)用函數(shù)都能得到一個(gè)新的包含期望結(jié)果的數(shù)組,肯定不能如愿了。函數(shù)add_to的參數(shù)target在函數(shù)第一次被解析的時(shí)候會(huì)被賦值成空的數(shù)組,因?yàn)橹粫?huì)被解析一次,以后每次調(diào)用的時(shí)候都會(huì)在這個(gè)target變量的基礎(chǔ)上進(jìn)行操作,變量的id值也完全一樣。想要得到預(yù)期的結(jié)果,可以為這種可變數(shù)據(jù)類型的參數(shù)指定一個(gè)None來表示空值:
1
2
3
4
|
a = ( 1 , 2 , 3 ) b = { "a" : 1 , "b" : 2 , "msg" : "hello" } test_list_param( * a) test_dict_param( * * b) |
在python的世界里,參數(shù)是按標(biāo)識(shí)符傳遞(粗暴點(diǎn)解釋就是按引用傳遞的),你需要擔(dān)心的是參數(shù)的類型是否是可變的:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> 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 |
可變的數(shù)據(jù)類型,函數(shù)局部作用域里面的任何改變會(huì)保留在數(shù)據(jù)上;不可變的數(shù)據(jù)類型,發(fā)生的任何改變都只會(huì)體現(xiàn)在新生成的局部變量上,如同上面的列子中所示的效果,讀者可以對(duì)比一下。