首页 > 代码库 > 函数可变参传值(python)

函数可变参传值(python)

1、定义方法的基本语法
def fun(n,m,...)
 ....
 ....
 ....
 (return n)

关于return:
1,return可以有,可以没有,
2,没有return的方法返回None,
3,return后面没有表达式也是返回None,
4,函数无法到达结尾也返回None。

例:

def test(a,b):

c=a+b

上函数没有return,故输入test(1,2),没有返回值。

def test(a,b):

c=a+b

return c

上函数加上了return,输入test(1,2)

 

2、 Python中函数的参数定义和可变参数

Python中函数可以没有参数,也可以由多个参数。

1.没有参数的情况:

def funcA():
  pass
    
显然,函数funcA没有参数(同时啥也不干:D)。

 

2.两个参数:

下面这个函数funcB就有两个参数了,
def funcB(a, b):
  print a
  print b
调用的时候,我们需要使用函数名,加上圆括号扩起来的参数列表,比如funcB(100, 99),执行结果是:
100
99
很明显,参数的顺序和个数要和函数定义中一致,如果执行funcB(100),Python会报错的:
TypeError: funcB() takes exactly 2 arguments (1 given)

 

3.形式参数:用函数的时候打乱参数传递的顺序

上面的例子里,调用函数的时候,传递的参数都是根据位置来跟函数定义里的参数表匹配的,比如funcB(100, 99)和funcB(99, 100)的执行结果是不一样的。在Python里,还支持一种用关键字参数(keyword argument)调用函数的办法,也就是在调用函数的时候,明确指定参数值付给那个形参。比如还是上面的funcB(a, b),我们通过这两种方式调用funcB(a=100, b=99)和funcB(b=99, a=100)
结果跟funcB(100, 99)都是一样的,因为我们在使用关键字参数调用的时候,指定了把100赋值给a,99赋值给b。也就是说,关键字参数可以让我们在调用函数的时候打乱参数传递的顺序!

另外,在函数调用中,可以混合使用基于位置匹配的参数和关键字参数,前题是先给出固定位置的参数,比如
def funcE(a, b, c):
  print a
  print b
  print c
调用funcE(100, 99, 98)和调用funcE(100, c=98, b=99)的结果是一样的。

 

4.设置参数的默认值

我们可以在函数定义中使用参数默认值,比如
def funcC(a, b=0):
  print a
  print b
在函数funcC的定义中,参数b有默认值,是一个可选参数,如果我们调用funcC(100),b会自动赋值为0。

 

5.参数默认值的继承性

下面的程序就会出现很奇怪的现象:
def f(a, L=[]):
    L.append(a)
    returnL

print(f(1))
print(f(2))
print(f(3))
结果:
[1]
[1, 2]
[1, 2, 3]  #结果有继承性,因为L设置了默认值

 

但是当不设置默认值的时候:

def f(a, L):
    L.append(a)
    returnL

print(f(1))
print(f(2))
print(f(3))

结果:
[1]
[2]
[3]  #结果没有继承性,因为L没有设置了默认值

实际上是可以解释的,因为,python是解释性的语言,不像C++那样,先编译一边,把东西准备好,在执行之前,函数已经成为一个很固定的东西。而python却不一样,那是解释性的,程序执行到那个函数定义的地方系统才在表中注册这个函数,并且对参数的默认值进行赋值,所以才容许你使用变量来赋值。第一次使用之后,我们知道L是函数内部的元素,再一次执行它就跟将前面的定义代码在copy过 去一样的。要知道解释性的语言就是这样,因为除了默认参数值以外其他的变量(包括参数),都需要从新赋值,所以这个不会显示出什么不同,倒是默认参数值, 可能继承上一次的数据。(实际上,其他的变量也会继承,只是在有一次使用之前都会被从新赋值,只是具有默认值的参数具有特殊性。它时常不会被赋值,这样, 上一次的数据就会被保存。简单的说:对函数的几次连续调用就跟将函数的内容重复放几遍一样,他们的变量都有继承的特性,只是具有默认值的参数的值会继承上次的数据。

 

6.带*的参数:用来接受可变数量参数

目前为止,我们要定义一个函数的时候,必须要预先定义这个函数需要多少个参数(或者说可以接受多少个参数)。一般情况下这是没问题的,但是也有在定义函数的时候,不能知道参数个数的情况(想一想C语言里的printf函数),在Python里,带*的参数就是用来接受可变数量参数的。看一个例子
def funcD(a, b, *c):
  print a
  print b
  print "length of c is: %d " % len(c)
  print c
调用funcD(1, 2, 3, 4, 5, 6)结果是
1
2
length of c is: 4
(3, 4, 5, 6)
我们看到,前面两个参数被a、b接受了,剩下的4个参数,全部被c接受了,c在这里是一个tuple。我们在调用funcD的时候,至少要传递2个参数,2个以上的参数,都放到c里了,如果只有两个参数,那么c就是一个empty tuple。

func(*args)  

传入的参数为以元组形式存在args中,如:

技术分享

 

func( **kwargs)

传入的参数为以字典形式存在args中,如:

技术分享

 

func(*args, **kwargs)

传入的顺序必须和定义顺序相同,这里是先不定参数列表,再是关键字参数字典,如:

技术分享

技术分享

 

7.带**的参数:

如果一个函数定义中的最后一个形参有 ** (双星号)前缀,所有正常形参之外的其他的关键字参数都将被放置在一个字典中传递给函数,比如:
def funcF(a, **b):
  print a
  for x in b:
    print x + ": " + str(b[x])
调用funcF(100, c=‘你好‘, b=200),执行结果
100
c: 你好
b: 200
大家可以看到,b是一个dict对象实例,它接受了关键字参数b和c。

 

8.有关*和**的最本质的意义:

在python中的函数,我们要注意两个特点,一个就关键字参数,一个就是任意参数。任意参数的本质意义是让函数能够接受任意多个参数,它的本质意义是用*args表示一个集合,等到这个参数赋值的时候,它会尽可能的接收它能接受的参数,形成一个集合。

也就是说,实际上,假设函数的形参还是与实参的个数是对应的,而*args的引入,就代表*args,表示有0到任意多个形参。同理**args(他是一个字典集合)。也就是说

def fun(n, *args):
是个函数定义其实就是def fun(n, args[0],args[1],args[2]....).到了函数内部*args就是一个集合。也就是说*这个符号具有拆分的意思,这个意思在另外一个地方就成为了作用了。

一个集合拆分成,分开的几个参数,而不是一个元素的集合。这里要分清楚,集合是一个对象(不管内部有几个元素),而是用*拆分后就是若干个对象了

技术分享

发现没有,实际上,args就是表达成一个集合,加上*,就表示多个元素了。

实际上:def fun(n,*args):
如果还原到普通函数就是这样的了:
def fun(n,args):
这是使用它的时候就是这样的:
fun(12, ["xu", "yong", "quan"])
*args在作为行参的时候,就表示,将这个集合拆分成若干个变量元素。这样就是:
def fun(n, args[0],args[1],args[2]....).

*args在作为实参(变量)的时候,也是拆分的意思。

技术分享

 

参考链接:http://blog.sina.com.cn/s/blog_6babbcb801018412.html

http://blog.sina.com.cn/s/blog_93b45b0f0100z3et.html

http://www.cnblogs.com/tqsummer/archive/2011/01/25/1944416.html

http://blog.csdn.net/xmnathan/article/details/39156697

函数可变参传值(python)