python中函数的默认参数陷阱问题
其实也不能说是陷阱,只是一个不容易注意到的地方,尤其是有其他java/c++类编程语言经验的人员,这里涉及到python的一个特点,所以笔者说是陷阱只是一个噱头而已。
def test(item, buf = []):
buf.append(buf)
print buf
非常简单的一个函数,功能非常简单,现在看下面的调用代码
test('younger')
test('shen')
输出:
['younger']
['younger', 'shen']
该函数初衷是希望当没有提供默认的buff参数的时候,建立一个空的列表,然后把一个对象添加到该列表中,并且打印, 但是程序的执行似乎并没有按照我们的意图来执行,似乎每个函数都共享了buff,但是我们明明每次都在参数列表中初始化了buff变量,分析如下:
python中的def语句在每次执行的时候都初始化一个函数对象,这个函数对象就是我们要调用的函数,可以把它当成一个一般的对象,只不过这个对象拥有一个可执行的方法和部分属性,对于参数中提供了初始值的参数,由于python中的函数参数传递的是对象,也可以认为是传地址,只有def的时候初始化一次,然后在调用者和被调用者中都是共享的,所以在 func.func_defaults中只能看到一个默认参数,在该函数对象被初始化的时候就已经存在了。
解决这个问题可以用这个方法
def test(item, buf = None):
if buf is None:
buf = []
buf.append(item)
print buf
这样在不给定buf参数的时候可以初始化一次buf,每次都是新的,所以不会出现上面的陷阱,其实这里的None只是占位符而已,用空[]也可以,只不过要需要这样写
def test(item, buf = []):
if len(buf) < 1:
buf = []
buf.append(item)
print buf
这样也可以解决问题,只是看起开不太好而已。
近期除了使用django进行web开发之外,打算重新开始学习linux和操作系统的东西,近期会制定学习计划开始执行。
python中函数的默认参数陷阱问题的更多相关文章
- Python中list作为默认参数的陷阱
在Python中,作为默认参数的一定要是不可变对象,如果是可变对象,就会出现问题,稍不注意,就会调入陷阱,尤其是初学者,比如我(┬_┬). 我们来看一个例子. def add(L=[]): L.app ...
- python定义函数时默认参数注意事项
如果在调用一个函数时,没有传递默认参数,则函数内的默认参数是对函数的默认参数属性__defaults__的引用, 如 def func(arg1=[]): arg1.append(2) 调用func时 ...
- C++中函数的默认参数
使用方法: (1)在函数声明或定义时,直接对参数赋值,该参数就是默认参数. (2)在函数调用时,省略部分或全部参数,这时就会使用默认参数进行代替. 注意事项: (1)一般在声明函数是设置默认参数. 如 ...
- 在python中,用默认参数(list,set,dict...)时要小心
在我们平时写需求的时候,如果没有了解到以下知识点,可能会出现这样的问题,掉进坑里面,甚至很难找到问题的根源.下面我们来看看使用可变默认参数(Mutable default arguments)时会出现 ...
- C++中函数的默认参数和C语言中volatile的学习
1.函数默认参数 1 int func(int a,int b=10) 2 { 3 return a*b; 4 } 5 6 int main() 7 { 8 int c=func(2); 9 cout ...
- Python 中函数的 收集参数 机制
定义函数的时候,在参数前加了一个 * 号,函数可以接收零个或多个值作为参数.返回结果是一个元组. 传递零个参数时函数并不报错,而是返回一个空元组.但以上这种方法也有局限性,它不能收集关键字参数. 对关 ...
- c++中 函数的默认参数 学习
默认参数指的是当函数调用中省略了实参时 自动使用一个默认的值. 对于带参数列表的函数,必须从右向左添加默认值 (就是说她的右边肯定是先有默认的值) fun(int ,1,2,3) 不能 fu ...
- 【转】Python函数默认参数陷阱
[转]Python函数默认参数陷阱 阅读目录 可变对象与不可变对象 函数默认参数陷阱 默认参数原理 避免 修饰器方法 扩展 参考 请看如下一段程序: def extend_list(v, li=[]) ...
- Python面试题目之Python函数默认参数陷阱
请看如下一段程序: def extend_list(v, li=[]): li.append(v) return li list1 = extend_list(10) list2 = extend_l ...
随机推荐
- HTML embed标签使用方法和属性详解
一.基本语法 代码如下: embed src=url 说明:embed可以用来插入各种多媒体,格式可以是 Midi.Wav.AIFF.AU.MP3等等,Netscape及新版的IE 都支持 ...
- C#中常用接口介绍
1. IComparable接口 IComparable接口定义通用的比较方法.由类型使用的IComparable接口提供了一种比较多个对象的标准方式.如果一个类要实现与其它对象的比较, 则必须实现I ...
- 面向新手的Webserver搭建(一)——IIS的搭建
非常多童鞋说自己是做移动开发的,想挂个简单的Web API,但是server又不会搭,这样一来測试就成了问题.看看网上的教程.发现略难懂,并且大多是一个转一个,没价值,所以干脆写几篇文章讲讲简单的We ...
- Directx 3D编程实例:绘制可变速旋转的三角形
最近朋友建议我写一些关于微软云技术的博客留给学校下一届的学生们看,怕下一届的MSTC断档.于是我也觉的有这个必要. 写了几篇博客之后,我觉得也有必要把这一年的学习内容放在博客做个纪念,就这样写了本篇博 ...
- 第十四章 红黑树——C++代码实现
红黑树的介绍 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉查找树.红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键 ...
- cocos2d-x项目过程记录(纹理和内存优化方面)
1.参考资料:Cocos2d-x纹理优化的一些方案 cocos2d-x如何优化内存的应用 iOS和android游戏纹理优化和内存优化(cocos2d-x) 2.加载贴图集纹理 CCSpriteF ...
- Effective C++ 总结(二)
四.设计与声明 条款18:让接口容易被正确使用,不易被误用 理想上,如果客户企图使用某个接口而却没有获得他所预期的行为,这个代码不该通过编译:如果代码通过了编译,它的行为就 ...
- Java基础知识强化之IO流笔记19:FileOutputStream的三个write方法
1. FileOutputStream的三个write方法: void write(byte[] buffer) Writes the entire contents of th ...
- Android(java)学习笔记216:多线程断点下载的原理(Android实现)
之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1.新建一个Android工程: (1)其中我们先实现布局 ...
- Python | 基础系列 · Python为什么没有switch/case语句?
与我之前使用的所有语言都不同,Python没有switch/case语句.为了达到这种分支语句的效果,一般方法是使用字典映射: def numbers_to_strings(argument): sw ...