Python函数参数操作详解
本文实例讲述了Python函数参数操作。分享给大家供大家参考,具体如下:
简述
在Python中,函数的定义非常简单,满足对应的语法格式要求即可。对于调用者来说,只需关注如何传递正确的参数,以及获取相应的返回值就足够了,无需了解函数的内部实现(除非想学习、跟踪源码)。
话虽如此,但对于函数的定义来说,灵活性非常高。除了常规定义的必选参数以外,还支持默认参数、可变参数、以及关键字参数。这样以来,不但能处理复杂的参数,还可以简化调用者的代码。
形参和实参
不止Python,几乎所有的编程语言都会涉及两个术语:parameter和argument。那么,它们之间究竟有什么区别呢?
parameter是指函数定义中的参数,而argument指的是函数调用时的实际参数。
简略描述:parameter=形参(formalparameter),argument=实参(actualparameter)。
例如,定义一个简单的函数:
>>>defgreet(param1,param2): ...pass ... >>> >>>greet('Hello','Python')
其中,param1和param2是函数的形参,而在函数greet()被调用时,传入的('Hello'和'Python')则是实参。
固定数量参数的函数
到目前为止,关于函数,我们介绍的都是固定数量的参数。来看一个简单的示例:
>>>defgreet(say,msg): ...print(say,msg) ... >>> >>>greet('Hello','Python') HelloPython
这里,函数greet()有两个参数,用两个参数调用这个函数,运行得很顺利,不会有任何错误。
倘若,参数的个数不匹配,会发生什么?
>>>greet()#没有参数 ... TypeError:greet()missing2requiredpositionalarguments:'say'and'msg' >>> >>>greet('Hi')#只有一个参数 ... TypeError:greet()missing1requiredpositionalargument:'msg'
显然,解释器会发牢骚。但是,对Python来说,要解决这个问题简直是易如反掌,继续往下看!
默认参数
定义函数时,可以使用赋值运算符(=)为参数指定一个默认值。
注意:如果参数没有默认值,在调用时必需为其指定一个值;如果参数有默认值,那么在调用时值是可选的,如果为其提供了一个值,将会覆盖默认值。
>>>defgreet(say,name='James',msg='Iamyourbiggestfan!'): ...print(say,',',name,',',msg) ... >>>greet('Hi')#只提供强制性的参数 Hi,James,Iamyourbiggestfan! >>> >>>greet('Hi','Kobe')#给出一个可选参数 Hi,Kobe,Iamyourbiggestfan! >>> >>>greet('Hi','Kobe','Iwanttochallengeyou!')#给出所有参数 Hi,Kobe,Iwanttochallengeyou!
由于say没有默认值,所以必须指定;name、msg有默认值,所以值是可选的。
函数中的所有参数都可以有默认值,但是,一旦存在一个默认参数,其右侧的所有参数也必须有默认值。也就是说,非默认参数不能在默认参数之后。
例如,将上面的函数定义为:
defgreet(name='James',say):
就会引发错误:
SyntaxError:non-defaultargumentfollowsdefaultargument
关键字参数
当使用某些值调用函数时,这些值将根据其位置分配给参数。
例如,在上述函数greet()中,当使用greet('Hi','Kobe')调用它时,'Hi'被赋值给参数say,同样地,'Kobe'被赋值给name。
Python允许使用kwarg=value格式的关键字参数调用函数:
>>>defgreet(say,name='James'): ...print(say,',',name) ... >>> >>>greet(say='Hi',name='Kobe')#2个关键字参数 Hi,Kobe >>> >>>greet(name='Kobe',say='Hi')#2个关键字参数(次序颠倒) Hi,Kobe >>> >>>greet('Hi',name='Kobe')#位置参数与关键字参数混合使用 Hi,Kobe
当以这种方式调用函数时,关键字参数必须在位置参数之后,所有传递的关键字参数都必须与函数接受的某个参数匹配,并且它们的顺序不重要。
例如,像下面这样调用,会引发错误:
>>>greet(name='Kobe','Hi')#关键字参数在位置参数之前 ... SyntaxError:positionalargumentfollowskeywordargument >>> >>>greet('Hi',na='Kobe')#na不匹配 ... TypeError:greet()gotanunexpectedkeywordargument'na'
可变参数
可变参数也被称为不定长参数,顾名思义,就是传入的参数个数是可变的,可以是任意个(0、1、2…N)。
要定义可变参数,仅需在参数名之前添加一个星号(*)。在函数内部,这些参数被包装为一个tuple。
注意:此*非彼*,不要误认为是C/C++中的指针。
>>>defgreet(*names): ...print(names) ... >>> >>>greet()#没有参数,返回空元组 () >>> >>>greet('Jordan','James','Kobe') ('Jordan','James','Kobe')
有时,必须在函数定义中使用位置参数以及可变参数,但位置参数始终必须在可变参数之前。
>>>defgreet(say,*names): ...print(say,names) ... >>> >>>greet('Hi') Hi() >>> >>>greet('Hi','Jordan','James','Kobe') Hi('Jordan','James','Kobe')
通常情况下,可变参数会出现在形参列表的最后,因为它们会把传递给函数的所有剩余输入参数都收集起来。可变参数之后出现的任何形参都是“强制关键字”参数,这意味着,它们只能被用作关键字参数,而不能是位置参数。
>>>defgreet(*names,sep=','): ...returnsep.join(names) ... >>> >>>greet('Jordan','James','Kobe') 'Jordan,James,Kobe' >>> >>>greet('Jordan','James','Kobe',sep='/')#被用作关键字参数 'Jordan/James/Kobe' >>> >>>greet('Jordan','James','Kobe','/')#被用作位置参数 'Jordan,James,Kobe,/'
任意关键字参数
还有一种机制,用于任意数量的关键字参数。为了做到这一点,使用双星号(**):
>>>defgreet(**all_star): ...print(all_star) ... >>>greet()#没有参数,返回空字典 {} >>> >>>greet(name='James',age=18) {'name':'James','age':18}
当最后一个形式为**msgs的形参出现时,它将收到一个字典,其中包含所有关键字参数,除了与形参对应的关键字参数之外。还可以与*names的形参相结合(*names必须出现在**msgs之前)。
例如,定义一个这样的函数:
>>>defgreet(say,*names,**msgs): ...print('--',say) ...fornameinnames: ...print(name) ...print('-'*40) ...keys=sorted(msgs.keys()) ...forkeyinkeys: ...print(key,':',msgs[key]) ... >>> >>>greet('Hi','Jordan','James','Kobe',msg='Iwanttochallengeyou!',challenger='Waleon') --Hi Jordan James Kobe ---------------------------------------- challenger:Waleon msg:Iwanttochallengeyou!
注意:在打印内容之前,通过对msgs字典的keys()方法的结果进行排序来创建关键字参数名称列表。如果没有这样做,则打印参数的顺序是未定义的。
对参数进行解包
正如“可变参数”那样,也可在函数调用中使用*操作符。只不过在这种情况下,与在函数定义中*的语义相反,参数将被解包而不是打包。
>>>defgreet(name,age): ...print(name,age) ... >>> >>>t=('James',18) >>>greet(*t) James18
还有一种方式,几乎没有必要提到,这里也罗嗦一下:
>>>greet(t[0],t[1]) James18
与解包相比,这种调用方式显然不舒适。另外,在一般情况下,调用greet(t[0],t[1])几乎是徒劳的,因为长度是未知的。“未知”的意思是:长度只在运行时才知道,而不是在编写脚本时就知道。
同样地,字典也可以用**操作符传递关键字参数:
>>>defgreet(name,age=18): ...print(name,age) ... >>> >>>d={'name':'James','age':32} >>>greet(**d) James32
Python获取函数参数个数:
Python2.7写法:
#-*-coding:utf-8-*- #!python2 defabc(a,b,c): printa,b yy=abc.func_code.co_argcount printyy
输出结果为
3
python3.6写法
#-*-coding:utf-8-*- #!python3 defabc(a,b,c): print(a,b) a=abc.__code__.co_argcount print(a)
输出结果为
3
使用场景:
比如在REST规范的代码中,request数据格式检验,判断携带参数个数是否符合该函数所需参数的个数,不是就可以returnerror了
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python函数使用技巧总结》、《Python数学运算技巧总结》、《Python数据结构与算法教程》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》
希望本文所述对大家Python程序设计有所帮助。