博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python中函数参数问题小究
阅读量:5364 次
发布时间:2019-06-15

本文共 4250 字,大约阅读时间需要 14 分钟。

python3中函数参数有位置参数、命名关键字参数、默认参数、非关键字可变长参数、关键字可变长参数几种。

一、位置参数

位置参数是函数的标准参数,是最常用的一种参数格式。定义函数时,由于每个参数都有自己的位置,如果不加以特殊说明,调用函数时,函数就会根据所赋参数的位置来给函数内参数赋值。

def s(x,y):    print('x=',x)    print('y=',y)a,b=1,0s(a,b)运行结果:x= 1y= 0

调用时,函数会自动将处在x位置的a参数赋给x,把参数b赋给y。

位置参数是必选参数,调用函数时,位置参数未赋值,函数将报错。

二、命名关键字参数

格式: def s(x,y,*,z,k)      print('x=',x)   print('y=',y)   print('z=',z)   print('k=',k)
a,b,c,d=4,3,2,1 s(a,b,k=c,z=d) 输出 x= 4 y= 3 z= 1 k= 2

此时,位置参数必须在最前,关键字参数在后,关键字参数之间可以不按顺序。

定义命名关键字参数时,需要使用*分割符,*后面的参数都是命名关键字参数。命名关键字参数在使用时,必须使用‘形参=’这种格式,不然将会报错

三、默认参数

默认参数是指在定义函数时,赋给该参数一个值。调用该函数时,如果未给该参数赋值,则函数会自动将定义时的值拿来使用。

 
def s(x,k='233'):     print('x=',x)     print('k=',k) a,b,c,d=4,3 s(a) s(a,b) s(a,k=c) 输出: x= 4 k= 233 x= 4 k= 3 x= 4 k= 4
可以看到,如果省略了k,则默认为是233,如果给k赋值,则以赋值为准。给k赋值时,可以采用位置参数的方式(不加想形参名字),也可以采取关键字参数的方式。 默认参数在定义时的位置必须在位置参数之后。调用的时候,也必须在位置参数之后,否则会报错。这是因为函数在给参数赋值的时候,会优先将值赋给位置参数,剩下如果有多余的值会再赋给默认参数,如果没有就采用默认值。
 

 注意,定义默认参数一定是不可变参数。如果是可变参数,可能会出现一些错误。参考廖雪峰老师微博:

先定义一个函数,传入一个list,添加一个END再返回:

def add_end(L=[]):    L.append('END')    return L 当你正常调用时,结果似乎不错: >>> add_end([1, 2, 3]) [1, 2, 3, 'END']
>>> add_end(['x', 'y', 'z']) ['x', 'y', 'z', 'END']

当你使用默认参数调用时,一开始结果也是对的:

>>> add_end()['END']

但是,再次调用add_end()时,结果就不对了:

>>> add_end()['END', 'END']>>> add_end()['END', 'END', 'END']

很多初学者很疑惑,默认参数是[],但是函数似乎每次都“记住了”上次添加了'END'后的list。

原因解释如下:

Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

 定义默认参数要牢记一点:默认参数必须指向不变对象!

要修改上面的例子,我们可以用None这个不变对象来实现:

def add_end(L=None):    if L is None: L = [] L.append('END') return L

现在,无论调用多少次,都不会有问题:

>>> add_end()['END']>>> add_end()['END']

为什么要设计strNone这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

 
如果函数中既有命名关键字参数,又有默认参数,两个参数必须都在位置参数之后。如果赋值时,默认参数赋值不使用‘k=’这样的格式,则必须严格按照定义函数时的位置来传递参数。如果使用‘k=’这种格式,在这两只参数在传递时位置没有特殊的要求。
但是在定义函数时,如果将默认参数放在命名关键参数之后,则表明这个参数既是默认参数,也是命名关键参数。
def s(x,k=233,*,y,z,j=111):    print('x=',x)    print('y=',y)    print('z=',z)    print('k=',k)    print('j=',j)a,b,c,d=4,3,2,1s(a,z=c,y=b,k=d)输出:x= 4y= 3z= 2k= 1j=111

四、非关键字可变长参数

非关键字可变长参数用 *变量名  来表示,定义函数时,一般用 *args 来表示。主要用来处理一些不能确定有多少个参数的问题。

函数将多余的不带关键字的参数打包成为一个元组,进行处理。*args后面的参数必须使用关键字,不然全都会被当成可变长参数,被打包到元组中。

但是,*args与默认参数之间顺序的问题也需要注意。

 
def s(x,y=233,*args):     print('x =',x)     print('y =',y)     for index,i in enumerate(args):         print('args[%s] = %s'%(index,i))     print(type(args)) s(1,2,3,4,5) 输出:

x = 1

y = 2
args[0] = 3
args[1] = 4
args[2] = 5
<class 'tuple'>

可以看到,该函数第一个值赋给位置参数,第二个值赋给默认参数,后面的值全都打包成为一个元组,通过for循环来显示。只要传递的参数传递的参数大于两个,就会自动给默认参数赋值,此时默认参数基本上失去了默认的意义。 

 也可以将默认参数放在*args的后面,但是此时给默认参数赋值时,需要加上关键字,不然就会被打包为元组,赋值给args。

def s(x,*args,y=233):    print('x =',x)    print('y =',y)    for index,i in enumerate(args):        print('args[%s] = %s'%(index,i))s(1,2,3,4,5)输出:x = 1y = 233args[0] = 2args[1] = 3args[2] = 4args[3] = 5 s(1,2,3,4,y=5)输出:x = 1y = 5args[0] = 2args[1] = 3args[2] = 4

列表或元组可以以作为参数传入*args,如果不想被二次打包,需要在列表或者元组前面加 * 。

def s(x,*args,y=233):    print('x =',x)    print('y =',y)    for index,i in enumerate(args):        print('args[%s] = %s'%(index,i))s(1,2,*[4,5,6])输出:x = 1y = 233args[0] = 2args[1] = 4args[2] = 5args[3] = 6

 

五、可变长的关键字参数

可变长关键字参数用 **变量名  来表示,定义函数时,一般用 **kwargs  来表示。主要用来处理一些不能确定有多少个关键字参数的问题。

函数将多余的带关键字的参数打包成为一个字典,关键字为字典的key,进行处理。**kwargs必须是放在函数形参的最后。

def s(x,*args,y=233,**kwargs):    print('x =',x)    print('y =',y)    for index,i in enumerate(args):        print('args[%s] = %s'%(index,i))    for i in kwargs:        print(i,'   ',kwargs[i])    print('kwargs type is ',type(kwargs))s(1,2,a=3,b=4)输出结果:x = 1y = 233args[0] = 2a     3b     4kwargs type is  

 

同样,字典也可以作为参数传入**kwargs,需要在字典前加 **

可以对比下列代码的执行结果:

def s(x,*args,y=233,**kwargs):    print('x =',x)    print('y =',y)    for index,i in enumerate(args):        print('args[%s] = %s'%(index,i))    for i in kwargs:        print(i,'   ',kwargs[i])s(1,2,{
'a':5})输出:x = 1y = 233args[0] = 2args[1] = {
'a': 5} #由于该字典不带关键字,会被当成一个非关键字参数打包入args。
s(1,2,a={
'a':5}) 输出: x = 1 y = 233 args[0] = 2 a {
'a': 5} # 此处,该字典带了关键字,会将该字典连同关键字一起进行打包,变为一个嵌套的字典。 s(1,2,**{
'a':5}) 输出: x = 1 y = 233 args[0] = 2 a 5 #由于字典前加上** ,该字典直接被加入kwargs中

 

转载于:https://www.cnblogs.com/ohahastudy/p/8097458.html

你可能感兴趣的文章
mysql (一)
查看>>
photoshop图层样式初识1
查看>>
【.NET】使用HtmlAgilityPack抓取网页数据
查看>>
typedef的使用
查看>>
基于位置的本地商铺个性化推荐
查看>>
职场上一个人情商高的十种表现
查看>>
【底层原理】深入理解Cache (下)
查看>>
Elasticsearch安装中文分词插件IK
查看>>
进阶4:常见函数-单行函数
查看>>
简述企业信息化与企业架构关系
查看>>
npoi List 泛型导出
查看>>
第七章笔记
查看>>
“滑机约拍”--第一阶段冲刺
查看>>
任务管理器隐藏一个进程
查看>>
MySQL死锁查询【原创】
查看>>
二维傅里叶变换的应用-相位相关
查看>>
元类type
查看>>
Linux网络协议栈(四)——链路层(1)
查看>>
Python运行机制
查看>>
Android应用性能优化之使用SparseArray替代HashMap
查看>>