python 中的函数参数是赋值式的传递的,函数的使用中要注意两个方面:1.函数参数的定义过程,2.函数参数在调用过程中是如何解析的。首先说一下在python 中的函数调用过程是分四种方式的,这里且先说五种,第五种已经在以前的文章中说过了

1.参数枚举的函数定义:

1. >>> def
2. return
3.   
4. >>> Fun(1,2,3)  
5. (1, 2, 3)  
6. >>> Fun(1,2) # 枚举参数个数不对应
7.   
8. Traceback (most recent call last):  
9. "<pyshell#61>", line 1, in
10. 1,2)  
11. TypeError: Fun() takes exactly 3 arguments (2
12. >>>


>>> def Fun(a,b,c):
	return (a,b,c)

>>> Fun(1,2,3)
(1, 2, 3)
>>> Fun(1,2) # 枚举参数个数不对应

Traceback (most recent call last):
  File "<pyshell#61>", line 1, in <module>
    Fun(1,2)
TypeError: Fun() takes exactly 3 arguments (2 given)
>>>

1. >>> def
2. print
3.   
4.       
5. >>> Fun(a=22,b=33,c=44)  
6. (22, 33, 44)  
7. >>> Fun(22,33,44)<span style="white-space:pre">  </span># 不指定赋值对象,就是按照顺序匹配
8. (22, 33, 44)  
9. >>> Fun(22,33,c=44)  <span style="white-space:pre">  </span># 可以指定参数的赋值对象,也可以不指定,
10. (22, 33, 44)  
11. >>> Fun(b=22,a=33,c=44) # 参数顺序可以不对应
12. (33, 22, 44)  
13. >>>


>>> def Fun(a,b,c):
	print (a,b,c)

	
>>> Fun(a=22,b=33,c=44)
(22, 33, 44)
>>> Fun(22,33,44)<span style="white-space:pre">	</span># 不指定赋值对象,就是按照顺序匹配
(22, 33, 44)
>>> Fun(22,33,c=44)  <span style="white-space:pre">	</span># 可以指定参数的赋值对象,也可以不指定,
(22, 33, 44)
>>> Fun(b=22,a=33,c=44) # 参数顺序可以不对应
(33, 22, 44)
>>>

这是最常见的定义方式,一个函数可以枚举定义任意多的参数,每个参数之间使用逗号隔开,用这种方式定义的函数在调用的时候实参的个数和形参的个数必须相等,并且顺序是一一对应的,如果出现参数数量不对或者参数类型不对应就会报错。

2.带默认参数的函数定义

1. >>> def Fun(a,b,c=33):  
2. print
3.   
4.       
5. >>> Fun(11,22) # 可以不写默认参数
6. (11, 22, 33)  
7. >>> Fun(1)     # 就是至少实参的个数和非默认参数的个数相同
8.   
9. Traceback (most recent call last):  
10. "<pyshell#66>", line 1, in
11. 1)  
12. TypeError: Fun() takes at least 2 arguments (1
13. >>> Fun(1,2,3) <span style="white-space:pre">    </span># 可以覆盖默认参数
14. (1, 2, 3)


>>> def Fun(a,b,c=33):
	print (a,b,c)

	
>>> Fun(11,22) # 可以不写默认参数
(11, 22, 33)
>>> Fun(1)     # 就是至少实参的个数和非默认参数的个数相同

Traceback (most recent call last):
  File "<pyshell#66>", line 1, in <module>
    Fun(1)
TypeError: Fun() takes at least 2 arguments (1 given)
>>> Fun(1,2,3) <span style="white-space:pre">	</span># 可以覆盖默认参数
(1, 2, 3)


这种方式就可以在调用的时候不填写默认参数了,但是要注意含有默认值的函数在定义的时候就已经把他的默认参数初始化了,这个在以前的文章也谈过。


3.不确定参数个数的函数定义:

1. >>> def
2. if 0
3. print 'None'
4. else:  
5. print
6.   
7.           
8. >>> Fun(1,2,3)  
9. (1, 2, 3)              # tuple 类型
10. >>> Fun(a=1,b=2,c=33)  # 不能在按照字典的方式赋值
11.   
12. Traceback (most recent call last):  
13. "<pyshell#93>", line 1, in
14. 1,b=2,c=33)  
15. TypeError: Fun() got an unexpected keyword argument 'a'
16. >>> Fun() # 可以是0参数
17. None


>>> def Fun(*a): 
	if 0 == len(a):
		print 'None'
	else:
		print a

		
>>> Fun(1,2,3)
(1, 2, 3)              # tuple 类型
>>> Fun(a=1,b=2,c=33)  # 不能在按照字典的方式赋值

Traceback (most recent call last):
  File "<pyshell#93>", line 1, in <module>
    Fun(a=1,b=2,c=33)
TypeError: Fun() got an unexpected keyword argument 'a'
>>> Fun() # 可以是0参数
None


这种带*号的说明参数的个数是不确定的,在调用的时候想传多少个 参数都行[0,n],呵呵,爽吧,但是他传入的参数都会放在一个

tuple中,如果有返回值的接受的时候也是用tuple行了,对于函数内部不确定的数量赋值时直接就循环迭代赋值就Ok了。


4.不确定个数的字典参数定义:

在定义的形参处加两个*,就是在函数内部处理函数的时候都是用字典的形式保存,当然调用的时候要用key=value的形式

1. >>> def
2. if 0
3. print 'None'
4. else:  
5. print
6.   
7.           
8. >>> Fun(1,2,3,4) # 字典赋值,这样就不行了
9.   
10. Traceback (most recent call last):  
11. "<pyshell#83>", line 1, in
12. 1,2,3,4)  
13. TypeError: Fun() takes exactly 0 arguments (4
14. >>> Fun(a=1,b=2,c=3) <span style="white-space:pre">      </span># 必须key=value的赋值
15. {'a': 1, 'c': 3, 'b': 2}  <span style="white-space:pre">  </span># dict 类型
16. >>> Fun(aa=3,b=333,d=44)  
17. {'aa': 3, 'b': 333, 'd': 44}


>>> def Fun(**a):
	if 0 == len(a):
		print 'None'
	else:
		print a

		
>>> Fun(1,2,3,4) # 字典赋值,这样就不行了

Traceback (most recent call last):
  File "<pyshell#83>", line 1, in <module>
    Fun(1,2,3,4)
TypeError: Fun() takes exactly 0 arguments (4 given)
>>> Fun(a=1,b=2,c=3) <span style="white-space:pre">		</span># 必须key=value的赋值
{'a': 1, 'c': 3, 'b': 2}  <span style="white-space:pre">	</span># dict 类型
>>> Fun(aa=3,b=333,d=44)
{'aa': 3, 'b': 333, 'd': 44}


最后一个关于函数参数赋值优先级的例子:

1. >>> def Fun(a,b,c=22,*d,**e):  
2. print
3.   
4.       
5. >>> Fun(1)  
6.   
7. Traceback (most recent call last):  
8. "<pyshell#98>", line 1, in
9. 1)  
10. TypeError: Fun() takes at least 2 arguments (1
11. >>> Fun(1,2)  
12. 1 2 22
13. >>> Fun(1,2,3)  
14. 1 2 3
15. >>> Fun(1,2,3,4,5)  # 默认顺序匹配把多余的参数匹配给tuple
16. 1 2 3 (4, 5) {}  
17. >>> Fun(1,2,3,4,5,aa=33,bb=33)   # 把字典赋值匹配给dict
18. 1 2 3 (4, 5) {'aa': 33, 'bb': 33}  
19. >>> Fun(a=3,c=4,b=2b)  
20. SyntaxError: invalid syntax  
21. >>> Fun(a=3,c=4,b=22)        <span style="white-space:pre">  </span> # 在字典赋值和枚举匹配赋值的时候优先考虑匹配赋值
22. 3 22 4
23. >>> Fun(b=22,a=22,e=(1,2,3))  
24. 22 22 22 () {'e': (1, 2, 3)}  
25. >>> Fun(b=22,c=77,2,3,4,5,6,)    # 没有给a 赋值,多一个逗号
26. SyntaxError: non-keyword arg after keyword arg  
27. >>> Fun(b=22,c=77,2,3,4,5,6,k=44)    
28. SyntaxError: non-keyword arg after keyword arg  
29. >>> Fun(b=22,c=77,a=44,2,3,4,5,6,)  
30. >>> Fun(1,2,3,(22,3334,34))   # 直接使用tuple的实参传递<br style="font-family: 'Microsoft YaHei';font-size:14px;" /><span style="font-family: 'Microsoft YaHei';font-size:14px;">1 2 3 ((22, 3334, 34),) {}</span><br style="font-family: 'Microsoft YaHei';font-size:14px;" />


>>> def Fun(a,b,c=22,*d,**e):
	print a,b,c,d,e

	
>>> Fun(1)

Traceback (most recent call last):
  File "<pyshell#98>", line 1, in <module>
    Fun(1)
TypeError: Fun() takes at least 2 arguments (1 given)
>>> Fun(1,2)
1 2 22 () {}
>>> Fun(1,2,3)
1 2 3 () {}
>>> Fun(1,2,3,4,5)  # 默认顺序匹配把多余的参数匹配给tuple
1 2 3 (4, 5) {}
>>> Fun(1,2,3,4,5,aa=33,bb=33)   # 把字典赋值匹配给dict
1 2 3 (4, 5) {'aa': 33, 'bb': 33}
>>> Fun(a=3,c=4,b=2b)
SyntaxError: invalid syntax
>>> Fun(a=3,c=4,b=22)        <span style="white-space:pre">	</span> # 在字典赋值和枚举匹配赋值的时候优先考虑匹配赋值
3 22 4 () {}
>>> Fun(b=22,a=22,e=(1,2,3))
22 22 22 () {'e': (1, 2, 3)}
>>> Fun(b=22,c=77,2,3,4,5,6,)    # 没有给a 赋值,多一个逗号
SyntaxError: non-keyword arg after keyword arg
>>> Fun(b=22,c=77,2,3,4,5,6,k=44)  
SyntaxError: non-keyword arg after keyword arg
>>> Fun(b=22,c=77,a=44,2,3,4,5,6,)
>>> Fun(1,2,3,(22,3334,34))   # 直接使用tuple的实参传递<br style="font-family: 'Microsoft YaHei';font-size:14px;" /><span style="font-family: 'Microsoft YaHei';font-size:14px;">1 2 3 ((22, 3334, 34),) {}</span><br style="font-family: 'Microsoft YaHei';font-size:14px;" />

可以看出这里函数参数的赋值方式是有所差别的,按照 1 ,2,3,4的优先级依次降低,也就是先为枚举形参赋值,再为默认参数赋值,然后多出来的就都组装在在tuple中传过去,给带*的参数,最后把key=value的形式组装成字典的形式传进去,给**的参数

5.修饰器的函数调用方式(不是函数的定义方式,只是一种函数调用约定):


@Fun