本文实例讲述了Python函数参数操作。分享给大家供大家参考,具体如下:
简述
在 Python 中,函数的定义非常简单,满足对应的语法格式要求即可。对于调用者来说,只需关注如何传递正确的参数,以及获取相应的返回值就足够了,无需了解函数的内部实现(除非想学习、跟踪源码)。
话虽如此,但对于函数的定义来说,灵活性非常高。除了常规定义的必选参数以外,还支持默认参数、可变参数、以及关键字参数。这样以来,不但能处理复杂的参数,还可以简化调用者的代码。
形参和实参
不止 Python,几乎所有的编程语言都会涉及两个术语:parameter 和 argument。那么,它们之间究竟有什么区别呢?
parameter 是指函数定义中的参数,而 argument 指的是函数调用时的实际参数。
简略描述:parameter = 形参(formal parameter), argument = 实参(actual parameter)。
例如,定义一个简单的函数:
> def greet(param1, param2): ... pass ... > > greet('Hello', 'Python')
其中,param1 和 param2 是函数的形参,而在函数 greet()
被调用时,传入的('Hello' 和 'Python')则是实参。
固定数量参数的函数
到目前为止,关于函数,我们介绍的都是固定数量的参数。来看一个简单的示例:
> def greet(say, msg): ... print(say, msg) ... > > greet('Hello', 'Python') Hello Python
这里,函数 greet()
有两个参数,用两个参数调用这个函数,运行得很顺利,不会有任何错误。
倘若,参数的个数不匹配,会发生什么?
> greet() # 没有参数 ... TypeError: greet() missing 2 required positional arguments: 'say' and 'msg' > > greet('Hi') # 只有一个参数 ... TypeError: greet() missing 1 required positional argument: 'msg'
显然,解释器会发牢骚。但是,对 Python 来说,要解决这个问题简直是易如反掌,继续往下看!
默认参数
定义函数时,可以使用赋值运算符(=)为参数指定一个默认值。
注意: 如果参数没有默认值,在调用时必需为其指定一个值;如果参数有默认值,那么在调用时值是可选的,如果为其提供了一个值,将会覆盖默认值。
> def greet(say, name = 'James', msg = 'I am your biggest fan!'): ... print(say, ',', name, ',', msg) ... > greet('Hi') # 只提供强制性的参数 Hi , James , I am your biggest fan! > > greet('Hi', 'Kobe') # 给出一个可选参数 Hi , Kobe , I am your biggest fan! > > greet('Hi', 'Kobe', 'I want to challenge you!') # 给出所有参数 Hi , Kobe , I want to challenge you!
由于 say 没有默认值,所以必须指定;name、msg 有默认值,所以值是可选的。
函数中的所有参数都可以有默认值,但是,一旦存在一个默认参数,其右侧的所有参数也必须有默认值。也就是说,非默认参数不能在默认参数之后。
例如,将上面的函数定义为:
def greet(name = 'James', say):
就会引发错误:
SyntaxError: non-default argument follows default argument
关键字参数
当使用某些值调用函数时,这些值将根据其位置分配给参数。
例如,在上述函数 greet()
中,当使用 greet('Hi', 'Kobe')
调用它时,'Hi' 被赋值给参数 say,同样地,'Kobe' 被赋值给 name。
Python 允许使用 kwarg = value
格式的关键字参数调用函数:
> def greet(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: positional argument follows keyword argument > > greet('Hi', na = 'Kobe') # na 不匹配 ... TypeError: greet() got an unexpected keyword argument 'na'
可变参数
可变参数也被称为不定长参数,顾名思义,就是传入的参数个数是可变的,可以是任意个(0、1、2 … N)。
要定义可变参数,仅需在参数名之前添加一个星号(*
)。在函数内部,这些参数被包装为一个 tuple
。
注意: 此 * 非彼 *,不要误认为是 C/C++ 中的指针。
> def greet(*names): ... print(names) ... > > greet() # 没有参数,返回空元组 () > > greet('Jordan', 'James', 'Kobe') ('Jordan', 'James', 'Kobe')
有时,必须在函数定义中使用位置参数以及可变参数,但位置参数始终必须在可变参数之前。
> def greet(say, *names): ... print(say, names) ... > > greet('Hi') Hi () > > greet('Hi', 'Jordan', 'James', 'Kobe') Hi ('Jordan', 'James', 'Kobe')
通常情况下,可变参数会出现在形参列表的最后,因为它们会把传递给函数的所有剩余输入参数都收集起来。可变参数之后出现的任何形参都是“强制关键字”参数,这意味着,它们只能被用作关键字参数,而不能是位置参数。
> def greet(*names, sep = ','): ... return sep.join(names) ... > > greet('Jordan', 'James', 'Kobe') 'Jordan,James,Kobe' > > greet('Jordan', 'James', 'Kobe', sep = '/') # 被用作关键字参数 'Jordan/James/Kobe' > > greet('Jordan', 'James', 'Kobe', '/') # 被用作位置参数 'Jordan,James,Kobe,/'
任意关键字参数
还有一种机制,用于任意数量的关键字参数。为了做到这一点,使用双星号(**
):
> def greet(**all_star): ... print(all_star) ... > greet() # 没有参数,返回空字典 {} > > greet(name = 'James', age = 18) {'name': 'James', 'age': 18}
当最后一个形式为 **msgs
的形参出现时,它将收到一个字典,其中包含所有关键字参数,除了与形参对应的关键字参数之外。还可以与 *names
的形参相结合(*names
必须出现在 **msgs
之前)。
例如,定义一个这样的函数:
> def greet(say, *names, **msgs): ... print('--', say) ... for name in names: ... print(name) ... print('-' * 40) ... keys = sorted(msgs.keys()) ... for key in keys: ... print(key, ':', msgs[key]) ... > > greet('Hi', 'Jordan', 'James', 'Kobe', msg = 'I want to challenge you!', challenger = 'Waleon') -- Hi Jordan James Kobe ---------------------------------------- challenger : Waleon msg : I want to challenge you!
注意: 在打印内容之前,通过对 msgs 字典的 keys()
方法的结果进行排序来创建关键字参数名称列表。如果没有这样做,则打印参数的顺序是未定义的。
对参数进行解包
正如“可变参数”那样,也可在函数调用中使用 *
操作符。只不过在这种情况下,与在函数定义中 *
的语义相反,参数将被解包而不是打包。
> def greet(name, age): ... print(name, age) ... > > t = ('James', 18) > greet(*t) James 18
还有一种方式,几乎没有必要提到,这里也罗嗦一下:
> greet(t[0], t[1]) James 18
与解包相比,这种调用方式显然不舒适。另外,在一般情况下,调用 greet(t[0], t[1])
几乎是徒劳的,因为长度是未知的。“未知”的意思是:长度只在运行时才知道,而不是在编写脚本时就知道。
同样地,字典也可以用 **
操作符传递关键字参数:
> def greet(name, age = 18): ... print(name, age) ... > > d = {'name':'James', 'age':32} > greet(**d) James 32
Python获取函数参数个数:
Python2.7写法:
# -*- coding:utf-8 -*- #! python2 def abc(a,b,c): print a,b yy=abc.func_code.co_argcount print yy
输出结果为
3
python3.6写法
# -*- coding:utf-8 -*- #! python3 def abc(a,b,c): print(a,b) a=abc.__code__.co_argcount print(a)
输出结果为
3
使用场景:
比如在REST规范的代码中,request数据格式检验,判断携带参数个数是否符合该函数所需参数的个数,不是就可以return error了
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python函数使用技巧总结》、《Python数学运算技巧总结》、《Python数据结构与算法教程》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》
希望本文所述对大家Python程序设计有所帮助。
Python,函数参数
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]