小议Python中自定义函数的可变参数的使用及注意点


Posted in Python onJune 21, 2016

可变参数

Python的可变参数有两种,一种是列表类型,一种是字典类型。列表类型类似 C 中的可变参数,定义方式为

def test_list_param(*args) :
  for arg in args :
    print arg

其中 args 是一个 tuple。
字典类型的可变参数:

def test_dict_param(**args) :
  for k, v in args.iteritems() :
    print k, v

其中 args 是一个 dictionary
可以分别传递 tuple 和 dictionary 给相应的可变参数,格式如下

a = (1, 2, 3)
b = {"a":1, "b":2, "msg":"hello"}
test_list_param(*a)
test_dict_param(**b)

带默认参数的函数

函数的带默认值参数能够很大程度上方便我们使用:一般情况下可以省略传参使用参数的默认值,也可以主动传参;调用的时候也不用在意参数的顺序方便使用,并且直接、显式;甚至还能用来当作魔法值,做一些逻辑上的控制。

但是由于python的默认值参数只会在函数定义处被解析一次,此后每次调用函数的时候,默认值参数都会是这个值了。碰到一些不可变的数据类型比如:整型,字符串,元祖之类的还好,但如果碰到可变类型的数据比如数组的话,就会有发生一些意想不到的事情。
让我们举一个简单的例子说明一下:

def add_to(num, target=[]):
  target.append(num)
  print id(target), target

add_to(1)
# Output: 39003656, [1]
add_to(2)
# Output: 39003656, [1, 2]
add_to(3)
# Output: 39003656, [1, 2, 3]

很显然如果你是想每次调用函数都能得到一个新的包含期望结果的数组,肯定不能如愿了。函数add_to的参数target在函数第一次被解析的时候会被赋值成空的数组,因为只会被解析一次,以后每次调用的时候都会在这个target变量的基础上进行操作,变量的id值也完全一样。想要得到预期的结果,可以为这种可变数据类型的参数指定一个None来表示空值:

a = (1, 2, 3)
b = {"a":1, "b":2, "msg":"hello"}
test_list_param(*a)
test_dict_param(**b)

在python的世界里,参数是按标识符传递(粗暴点解释就是按引用传递的),你需要担心的是参数的类型是否是可变的:

>>> def test(param1, param2):
...   print id(param1), id(param2)
...   param1 += 1
...   param2 += 1
...   print id(param1), id(param2)
...
>>> var1 = 1
>>> var2 = 2
>>> print id(var1), id(var2)
36862728 36862704
>>> test(var1, var2)
36862728 36862704
36862704 36862680

可变的数据类型,函数局部作用域里面的任何改变会保留在数据上;不可变的数据类型,发生的任何改变都只会体现在新生成的局部变量上,如同上面的列子中所示的效果,读者可以对比一下。

Python 相关文章推荐
Python函数式编程指南(一):函数式编程概述
Jun 24 Python
Python实现爬取逐浪小说的方法
Jul 07 Python
使用Python实现博客上进行自动翻页
Aug 23 Python
python 函数传参之传值还是传引用的分析
Sep 07 Python
Python实现的爬取小说爬虫功能示例
Mar 30 Python
Tensorflow 实现将图像与标签数据转化为tfRecord文件
Feb 17 Python
Python标准库json模块和pickle模块使用详解
Mar 10 Python
浅谈Python中re.match()和re.search()的使用及区别
Apr 14 Python
使用 django orm 写 exists 条件过滤实例
May 20 Python
解决pytorch多GPU训练保存的模型,在单GPU环境下加载出错问题
Jun 23 Python
Anaconda使用IDLE的实现示例
Sep 23 Python
关于Numpy之repeat、tile的用法总结
Jun 02 Python
简单讲解Python编程中namedtuple类的用法
Jun 21 #Python
Python编程中实现迭代器的一些技巧小结
Jun 21 #Python
Centos Python2 升级到Python3的简单实现
Jun 21 #Python
Python的Django框架中forms表单类的使用方法详解
Jun 21 #Python
Python正则表达式使用经典实例
Jun 21 #Python
常见的python正则用法实例讲解
Jun 21 #Python
实例讲解Python的函数闭包使用中应注意的问题
Jun 20 #Python
You might like
php中生成随机密码的自定义函数代码
2013/10/21 PHP
php顺序查找和二分查找示例
2014/03/27 PHP
一个简单的PHP验证码实现代码
2014/05/10 PHP
基于PHP实现通过照片获取ip地址
2016/04/26 PHP
THINKPHP截取中文字符串函数实例代码
2017/03/20 PHP
php框架知识点的整理和补充
2021/03/01 PHP
一个用javascript写的select支持上下键、首字母筛选以及回车取值的功能
2009/09/09 Javascript
javascript中的变量是传值还是传址的?
2010/04/19 Javascript
基于jQuery的仿flash的广告轮播
2010/11/05 Javascript
jquery判断浏览器类型的代码
2012/11/05 Javascript
js数组操作学习总结
2013/11/04 Javascript
javascript对象的使用和属性操作示例详解
2014/03/02 Javascript
初识Node.js
2014/09/03 Javascript
JavaScript实现向setTimeout执行代码传递参数的方法
2015/04/16 Javascript
javascript和jquery实现用户登录验证
2016/05/04 Javascript
详谈angularjs中路由页面强制更新的问题
2017/04/24 Javascript
基于react组件之间的参数传递(详解)
2017/09/05 Javascript
seajs中模块依赖的加载处理实例分析
2017/10/10 Javascript
实例分析JS与Node.js中的事件循环
2017/12/12 Javascript
vue ssr 指南详读
2018/06/29 Javascript
原生JS实现留言板功能
2020/02/08 Javascript
微信小程序实现录制、试听、上传音频功能(带波形图)
2020/02/27 Javascript
[04:22]DOTA2上海特级锦标赛主赛事第四日TOP10
2016/03/06 DOTA
[41:21]夜魇凡尔赛茶话会 第三期02:看图识人
2021/03/11 DOTA
Python生成随机验证码的两种方法
2015/12/22 Python
Python的collections模块中namedtuple结构使用示例
2016/07/07 Python
Python中的pack和unpack的使用
2018/03/12 Python
如何基于Python实现电子邮件的发送
2019/12/16 Python
python GUI库图形界面开发之PyQt5 Qt Designer工具(Qt设计师)详细使用方法及Designer ui文件转py文件方法
2020/02/26 Python
Django-rest-framework中过滤器的定制实例
2020/04/01 Python
深入浅析pycharm中 Make available to all projects的含义
2020/09/15 Python
利用HTML5 Canvas制作一个简单的打飞机游戏
2015/05/11 HTML / CSS
瑞典领先的汽车零部件网上零售商:bildelaronline24.se
2017/01/12 全球购物
英国PC组件和在线电脑商店:SCAN
2019/04/18 全球购物
2015年试用期工作总结
2014/12/12 职场文书
运动会口号霸气押韵
2015/12/24 职场文书