Python如何定义有默认参数的函数


Posted in Python onAugust 10, 2020

问题

你想定义一个函数或者方法,它的一个或多个参数是可选的并且有一个默认值。

解决方案

定义一个有可选参数的函数是非常简单的,直接在函数定义中给参数指定一个默认值,并放到参数列表最后就行了。例如:

def spam(a, b=42):
  print(a, b)

spam(1) # Ok. a=1, b=42
spam(1, 2) # Ok. a=1, b=2

如果默认参数是一个可修改的容器比如一个列表、集合或者字典,可以使用None作为默认值,就像下面这样:

# Using a list as a default value
def spam(a, b=None):
  if b is None:
    b = []
  ...

如果你并不想提供一个默认值,而是想仅仅测试下某个默认参数是不是有传递进来,可以像下面这样写:

_no_value = object()

def spam(a, b=_no_value):
  if b is _no_value:
    print('No b value supplied')
  ...

我们测试下这个函数:

>>> spam(1)
No b value supplied
>>> spam(1, 2) # b = 2
>>> spam(1, None) # b = None
>>>

仔细观察可以发现到传递一个None值和不传值两种情况是有差别的。

讨论

定义带默认值参数的函数是很简单的,但绝不仅仅只是这个,还有一些东西在这里也深入讨论下。

首先,默认参数的值仅仅在函数定义的时候赋值一次。试着运行下面这个例子:

>>> x = 42
>>> def spam(a, b=x):
...   print(a, b)
...
>>> spam(1)
1 42
>>> x = 23 # Has no effect
>>> spam(1)
1 42
>>>

注意到当我们改变x的值的时候对默认参数值并没有影响,这是因为在函数定义的时候就已经确定了它的默认值了。

其次,默认参数的值应该是不可变的对象,比如None、True、False、数字或字符串。 特别的,千万不要像下面这样写代码:

def spam(a, b=[]): # NO!
  ...

如果你这么做了,当默认值在其他地方被修改后你将会遇到各种麻烦。这些修改会影响到下次调用这个函数时的默认值。比如:

>>> def spam(a, b=[]):
...   print(b)
...   return b
...
>>> x = spam(1)
>>> x
[]
>>> x.append(99)
>>> x.append('Yow!')
>>> x
[99, 'Yow!']
>>> spam(1) # Modified list gets returned!
[99, 'Yow!']
>>>

这种结果应该不是你想要的。为了避免这种情况的发生,最好是将默认值设为None, 然后在函数里面检查它,前面的例子就是这样做的。

在测试None值时使用 is 操作符是很重要的,也是这种方案的关键点。 有时候大家会犯下下面这样的错误:

def spam(a, b=None):
  if not b: # NO! Use 'b is None' instead
    b = []
  ...

这么写的问题在于尽管None值确实是被当成False, 但是还有其他的对象(比如长度为0的字符串、列表、元组、字典等)都会被当做False。 因此,上面的代码会误将一些其他输入也当成是没有输入。比如:

>>> spam(1) # OK
>>> x = []
>>> spam(1, x) # Silent error. x value overwritten by default
>>> spam(1, 0) # Silent error. 0 ignored
>>> spam(1, '') # Silent error. '' ignored
>>>

最后一个问题比较微妙,那就是一个函数需要测试某个可选参数是否被使用者传递进来。 这时候需要小心的是你不能用某个默认值比如None、 0或者False值来测试用户提供的值(因为这些值都是合法的值,是可能被用户传递进来的)。 因此,你需要其他的解决方案了。

为了解决这个问题,你可以创建一个独一无二的私有对象实例,就像上面的_no_value变量那样。 在函数里面,你可以通过检查被传递参数值跟这个实例是否一样来判断。 这里的思路是用户不可能去传递这个_no_value实例作为输入。 因此,这里通过检查这个值就能确定某个参数是否被传递进来了。

这里对 object() 的使用看上去有点不太常见。object 是python中所有类的基类。 你可以创建 object 类的实例,但是这些实例没什么实际用处,因为它并没有任何有用的方法, 也没有任何实例数据(因为它没有任何的实例字典,你甚至都不能设置任何属性值)。 你唯一能做的就是测试同一性。这个刚好符合我的要求,因为我在函数中就只是需要一个同一性的测试而已。

以上就是Python如何定义有默认参数的函数的详细内容,更多关于Python定义有默认参数的函数的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
常用python数据类型转换函数总结
Mar 11 Python
Python中的ConfigParser模块使用详解
May 04 Python
Python编程中的文件读写及相关的文件对象方法讲解
Jan 19 Python
python生成tensorflow输入输出的图像格式的方法
Feb 12 Python
python脚本实现验证码识别
Jun 07 Python
Windows系统下PhantomJS的安装和基本用法
Oct 21 Python
Python定时发送消息的脚本:每天跟你女朋友说晚安
Oct 21 Python
python: 判断tuple、list、dict是否为空的方法
Oct 22 Python
python tkinter canvas使用实例
Nov 04 Python
使用opencv将视频帧转成图片输出
Dec 10 Python
Python脚本如何在bilibili中查找弹幕发送者
Jun 04 Python
Pycharm配置lua编译环境过程图解
Nov 28 Python
如何更换python默认编辑器的背景色
Aug 10 #Python
django前端页面下拉选择框默认值设置方式
Aug 09 #Python
解决Django响应JsonResponse返回json格式数据报错问题
Aug 09 #Python
django 获取字段最大值,最新的记录操作
Aug 09 #Python
在django中查询获取数据,get, filter,all(),values()操作
Aug 09 #Python
Python 使用双重循环打印图形菱形操作
Aug 09 #Python
Python 添加文件注释和函数注释操作
Aug 09 #Python
You might like
php str_replace的替换漏洞
2008/03/15 PHP
PHP中查询SQL Server或Sybase时TEXT字段被截断的解决方法
2009/03/10 PHP
php curl登陆qq后获取用户信息时证书错误
2015/02/03 PHP
Laravel 5 框架入门(四)完结篇
2015/04/09 PHP
PHP实现简单计算器小程序
2020/08/28 PHP
用JS实现一个TreeMenu效果分享
2011/08/28 Javascript
JQuery+DIV自定义滚动条样式的具体实现
2013/06/25 Javascript
Jquery结合HTML5实现文件上传
2015/06/25 Javascript
深入学习JavaScript对象
2015/10/13 Javascript
基于JS实现导航条之调用网页助手小精灵的方法
2016/06/17 Javascript
JavaScript实现使用Canvas绘制图形的基本教程
2016/10/27 Javascript
微信公众号开发 自定义菜单跳转页面并获取用户信息实例详解
2016/12/08 Javascript
Vue2.0 给Tab标签页和页面切换过渡添加样式的方法
2018/03/13 Javascript
vue2.0路由切换后页面滚动位置不变BUG的解决方法
2018/03/14 Javascript
浅谈Vue路由快照实现思路及其问题
2018/06/07 Javascript
JS实现获取word文档内容并输出显示到html页面示例
2018/06/23 Javascript
关于vue-cli 3配置打包优化要点(推荐)
2019/04/22 Javascript
javascript将扁平的数据转为树形结构的高效率算法
2020/02/27 Javascript
Python脚本文件打包成可执行文件的方法
2015/06/02 Python
CentOS 6.X系统下升级Python2.6到Python2.7 的方法
2016/10/12 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
2017/08/24 Python
终端命令查看TensorFlow版本号及路径的方法
2018/06/13 Python
python实现批量nii文件转换为png图像
2019/07/18 Python
Python分割训练集和测试集的方法示例
2019/09/19 Python
Python+OpenCV实现实时眼动追踪的示例代码
2019/11/11 Python
在Python中使用MongoEngine操作数据库教程实例
2019/12/03 Python
python代码实现TSNE降维数据可视化教程
2020/02/28 Python
Python2.7:使用Pyhook模块监听鼠标键盘事件-获取坐标实例
2020/03/14 Python
Python调用OpenCV实现图像平滑代码实例
2020/06/19 Python
欧舒丹澳洲版:L’OCCITANE
2017/07/17 全球购物
电大物流学生的自我评价
2013/10/25 职场文书
2014全国两会学习心得体会2000字
2014/03/10 职场文书
节约用水演讲稿
2014/05/21 职场文书
工作失职造成投诉的检讨书范文
2014/10/05 职场文书
副总经理岗位职责
2015/02/02 职场文书
《半截蜡烛》教学反思
2016/02/19 职场文书