设为首页 收藏本站
查看: 922|回复: 0

[经验分享] Python函数参数传递机制

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-4-5 10:57:39 | 显示全部楼层 |阅读模式
      最近在写代码的过程中,发现Python参数传递不是很明白。Python确实很灵活,但是灵活的后果就是要花更多的时间去研究。废话不多说,始めましょう!!!
Python参数传递有一下几种方式:

1:位置参数
Fun(arg1,arg2,...)
2:默认值参数
Fun(arg1,arg2=<value>...)
3:关键字参数
Fun(arg1=<value>,arg2=<value>...)
4:过量位置参数
Fun(arg1,arg2,*arg3)
5:过量关键字参数
Fun(arg1,arg2,**arg3)
6:混合参数
Fun(arg1,arg2=<value>,*arg3,**arg4)

一:位置参数
Fun(arg1,arg2,...)
位置参数在所有的开发语言中基本都有,这种方式函数声明了几个参数,在调用的时候就必须传几个参数,并且传递参数的位置也要跟声明函数的参数位置必须一致。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In [64]: def demo(a,b):
   ....:     return a+b
   ....:

In [65]: demo(1)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-65-cd1a36a59e96> in <module>()
----> 1 demo(1)

TypeError: demo() takes exactly 2 arguments (1 given)

In [66]: demo(1,2)
Out[66]: 3

In [67]:



这种方式比较简单,就不做太多说明。


二:默认值传递
Fun(arg1,arg2=<value>...)
我个人认为,默认值传递和第三种的关键字传递结合在一起说明比较好,因为大多数情况下,默认值传递本身就要使用关键字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
In [67]: def demo(a,b=2):
   ....:     return a+b
   ....:

In [68]: demo(2)
Out[68]: 4

In [69]: demo(4,5)
Out[69]: 9

In [70]: demo(a=4)
Out[70]: 6

In [71]: demo(a=4,b=5)
Out[71]: 9

In [72]: demo(b=5)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-72-f88a17b9de38> in <module>()
----> 1 demo(b=5)

TypeError: demo() takes at least 1 argument (1 given)

In [73]: demo(b=5,a=3)
Out[73]: 8



在声明函数demo的时候,给参数b付了一个默认值2,所以在调用demo的时候,可以只给a传递,在函数内部计算的时候就使用的是b的默认值。
如果在调用的时候给b传了一个值,那就使用传递的值,而不是使用默认值。
但是这种情况下,参数a是必须的,所以在调用的时候必须给a传值,否则将报错。因为参数b有默认值,所以即使不给b传值,也是可以的,将使用默认值。
在声明函数的时候,参数列表中有参数的名称,所以可以通过指定变量名的形式传递参数,并且变量的位置可以改变,这样Python内部自己就会去对应哪个实参该传给哪个形参。

三:关键字传递
Fun(arg1=<value>,arg2=<value>...)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [79]: def demo(a=1,b=2,c=3):
   ....:     return a+b+c
   ....:

In [81]: demo(4,5,6)
Out[81]: 15

In [82]: demo(4)
Out[82]: 9

In [83]: demo(b=4)
Out[83]: 8

In [84]: demo(b=8,a=5,c=3)
Out[84]: 16



理解了上面默认值传递的形式,再看关键字传递就很容易理解了,所以就不在做太多的解释。

四:过量位置参数
Fun(arg1,arg2,*arg3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
In [94]: def demo(a,b,*args):
   ....:     print a+b
   ....:     print type(args)
   ....:     print args
   ....:     

In [95]: demo(1,2,3,4,5)
3
<type 'tuple'>
(3, 4, 5)

In [100]: demo(1,2,3)
3
<type 'tuple'>
(3,)

In [98]: demo(1,23)
24
<type 'tuple'>
()

In [101]: demo(1)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-101-cd1a36a59e96> in <module>()
----> 1 demo(1)

TypeError: demo() takes at least 2 arguments (1 given)



如上面的代码所示:声明的函数demo中,参数a和b是必须参数,所以a和b是必须的,也就是说在调用demo函数的时候,至少需要传递两个参数,否则将出错。
过量位置参数使用星号(*)加变量名的形式(*args),在传递多余2个参数的时候,前两个参数分别赋值给了a和b,后面的参数都将整体赋值给args,通过打印可以看出,args是一个元祖类型,所以可以通过遍历将里面的数据取出来使用。

五:过量关键字参数
Fun(arg1,arg2,**arg3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
In [103]: def demo(a,b,**kwargs):
   .....:     print a+b
   .....:     print type(kwargs)
   .....:     print kwargs
   .....:     

In [104]: demo(1,2)
3
<type 'dict'>
{}

In [105]: demo(1,2,c=1)
3
<type 'dict'>
{'c': 1}

In [106]: demo(1,2,c=1,d=2)
3
<type 'dict'>
{'c': 1, 'd': 2}

In [107]: demo(1,2,3,c=1,d=2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-107-94e09001d957> in <module>()
----> 1 demo(1,2,3,c=1,d=2)

TypeError: demo() takes exactly 2 arguments (5 given)

In [108]: demo(1,2,3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-108-856c09b109ab> in <module>()
----> 1 demo(1,2,3)

TypeError: demo() takes exactly 2 arguments (3 given)



过量关键字使用两个星号加变量名的形式,即(**kwargs)
在之前的介绍关键字参数的时候可以看出,关键字参数一般都以键值对的形式存在,在过量关键字参数中也是,kwargs只接受键值对形式的参数,所以像107和108这两种调用方式就会出错,值1和2分别赋值给了a和b,后面的c=1和d=2通过kwargs来接受,剩余的3没有形式参数来接受,所以就会报错。因为**kwargs值接受键值对形式的参数。

六:混合参数
Fun(arg1,arg2=<value>,*arg3,**arg4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
In [109]: def demo(a,b,c=1,*args,**kwargs):
   .....:     print a+b+c
   .....:     print args
   .....:     print kwargs
   .....:     

In [110]: demo(2,3)
6
()
{}

In [111]: demo(2,3,4)
9
()
{}

In [112]: demo(2,3,4,5)
9
(5,)
{}

In [113]: demo(2,3,4,5,6)
9
(5, 6)
{}

In [114]: demo(2,3,4,5,6,d=1,e=2)
9
(5, 6)
{'e': 2, 'd': 1}



如上面代码所示,混合参数就是将前面介绍的几种形式结合起来一起使用。
a和b是位置参数,c是默认值参数,args是过量位置参数,kwargs是过量关键字参数。
理解了上面说的几种形式,再来理解混合参数形式应该比较简单,就不做过多的解释。

下面通过混合实例的形式,说明一下具体的使用。
首先定义函数如下
1
2
3
4
5
In [109]: def demo(a,b,c=1,*args,**kwargs):
   .....:     print a+b+c
   .....:     print args
   .....:     print kwargs
   .....:




实例1:

1
2
3
4
5
6
7
In [115]: demo(2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-115-5fc919890c38> in <module>()
----> 1 demo(2)

TypeError: demo() takes at least 2 arguments (1 given)



在调用函数的时候只传了一个值,但是从函数定义来看,a和b时必须的,只传了一个值,相当于只给a赋值了,b没有赋值,所以会报错。

实例2
1
2
3
4
5
6
7
In [117]: demo(2,3,a=4)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-117-803c2126718d> in <module>()
----> 1 demo(2,3,a=4)

TypeError: demo() got multiple values for keyword argument 'a'



上面调用函数出错的原因是因为没有按照正确的顺序给demo赋值,不能就认为指定a=4,就会在调用的时候就将4赋值给了a,剩下两个值2和3分别赋值给b和c,这是错误的,在这种混合模式下,赋值顺序必须是先位置参数->默认值参数->过量位置参数->过量关键字参数,否则就会出错。再看下面这个例子。
1
2
3
4
5
6
7
8
9
10
In [119]: demo(1,2,3,d=2,5,6)
  File "<ipython-input-119-6a415509517c>", line 1
    demo(1,2,3,d=2,5,6)
SyntaxError: non-keyword arg after keyword arg


In [120]: demo(1,2,3,5,6,d=2,)
6
(5, 6)
{'d': 2}



1,2,3分别赋值给了a,b,c,这没有问题,但是将d=2过量关键字参数放在了5,6过量位置参数前面,就出现了报错,将两者的顺序调换一下就没有问题。

重新定义函数demo,之后的实例将使用新定义的函数
1
2
3
In [121]: def demo(a,b,c):
   .....:     return a+b+c
   .....:




实例3
1
2
3
4
5
6
7
8
9
10
11
In [122]: demo(a=1,2,3)
  File "<ipython-input-122-ec666e77af79>", line 1
    demo(a=1,2,3)
SyntaxError: non-keyword arg after keyword arg


In [123]: demo(1,2,c=3)
Out[123]: 6

In [124]: demo(a=1,b=2,c=3)
Out[124]: 6



如上面的代码所示:
[122]在调用函数demo的时候在最前面指定了a的值,出现了错误,错误信息翻译成中文意思是:不要在关键字参数后使用位置参数。
[123]的调用方式就不会出现错误。所以在调用函数的时候,使用关键字形式传参一定要在位置传参的后面。

实例4
1
2
3
4
5
6
7
8
9
10
11
12
In [125]: args = (2,3)

In [126]: demo(1,*args)
Out[126]: 6

In [127]: demo(a=1,*args)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-127-aeb489dc72f3> in <module>()
----> 1 demo(a=1,*args)

TypeError: demo() got multiple values for keyword argument 'a'



上面[126]调用的时候,通过一个元祖包装了2个参数值,1赋值给形参a,元祖args中的2,3分别赋值给了形参b和c。
但是[127]的调用形式就会出错,其调用形式可以看成demo(a=1,2,3),原因就跟上面实例3的情况差不多,因为Python中“关键字形式传参一定要在位置传参的后面”,所以Python在赋值的时候,将先将2赋值给a,将3赋值给b,最后又将a=1赋值给a,所以就会出现上述的错误信息。

如果换一种形式传参,将2和3分装到字典中,就不会出现这种错误,如下代码所示
1
2
3
4
5
6
7
8
9
10
In [129]: dict={'b':2,'c':3}

In [130]: demo(a=1,**dict)
Out[130]: 6

In [131]: demo(**dict,a=1)
  File "<ipython-input-131-cd33424dd41b>", line 1
    demo(**dict,a=1)
               ^
SyntaxError: invalid syntax



将参数包装到字典中,就相当于所有的参数都是用关键字参数的形式传递,即demo(a=1,b=2,c=3),所以就不会出错。

综上所述,在传递参数的时候,一定要遵循参数传递的顺序,即位置参数->默认值参数->过量位置参数->过量关键字参数


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-199959-1-1.html 上篇帖子: python中的列表 下篇帖子: python中的字符串
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表