最近在写代码的过程当中,发现Python参数传递不是很明白。Python确实很灵活,可是灵活的后果就是要花更多的时间去研究。废话很少说,始めましょう!!!python
Python参数传递有一下几种方式:
ide
1:位置参数函数
Fun(arg1,arg2,...)spa
2:默认值参数翻译
Fun(arg1,arg2=<value>...)orm
3:关键字参数ip
Fun(arg1=<value>,arg2=<value>...)开发
4:过量位置参数input
Fun(arg1,arg2,*arg3)it
5:过量关键字参数
Fun(arg1,arg2,**arg3)
6:混合参数
Fun(arg1,arg2=<value>,*arg3,**arg4)
一:位置参数
Fun(arg1,arg2,...)
位置参数在全部的开发语言中基本都有,这种方式函数声明了几个参数,在调用的时候就必须传几个参数,而且传递参数的位置也要跟声明函数的参数位置必须一致。
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>...)
我我的认为,默认值传递和第三种的关键字传递结合在一块儿说明比较好,由于大多数状况下,默认值传递自己就要使用关键字。
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>...)
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)
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)
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)
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是过量关键字参数。
理解了上面说的几种形式,再来理解混合参数形式应该比较简单,就不作过多的解释。
下面经过混合实例的形式,说明一下具体的使用。
首先定义函数以下
In [109]: def demo(a,b,c=1,*args,**kwargs): .....: print a+b+c .....: print args .....: print kwargs .....:
实例1:
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
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,这是错误的,在这种混合模式下,赋值顺序必须是先位置参数->默认值参数->过量位置参数->过量关键字参数,不然就会出错。再看下面这个例子。
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,以后的实例将使用新定义的函数
In [121]: def demo(a,b,c): .....: return a+b+c .....:
实例3
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
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分装到字典中,就不会出现这种错误,以下代码所示
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),因此就不会出错。
综上所述,在传递参数的时候,必定要遵循参数传递的顺序,即位置参数->默认值参数->过量位置参数->过量关键字参数。