python 当list,dic作为默认参数的正确写法
来源:互联网 发布:模拟加密狗软件 编辑:程序博客网 时间:2024/05/21 08:59
面试题之一。
def extendList(val,list=[]): list.append(val) return listlist1 = extendList(10)list2 = extendList(123,[])list3 = extendList('a')print list1print list2print list3结果:
我猜应该是[10],[123],['a'],但实际上是:
[10, 'a'][123][10, 'a']
被面试官虐杀的我,查找了资料了,看看下面的有问题的代码:
def foo(a, b =[]): b.append(a) print bfoo(1)foo(2)
结果想象中是:
>>> [1][2]>>>实际上是:
>>> [1][1, 2]>>>
原来当list等可变类型作为默认参数时,仅仅在定义函数的时候(也就是执行def语句)被计算一次,有且仅有这么一次。
其它的时候无论调用几次函数,如果没有传参进来,就会一直用这个默认参数了。
看起来有点像是静态变量,静态变量的初始化也仅仅是执行一次。
为了验证下上述的几句话,我们需要先介绍下一些小工具:
id(obj),查看一个对象的id,如果两个对象的id是一样的,意味着他们是同一个对象。
func.__defaults__,是一个列表,存放着函数的默认参数的一个list,因为b()只有一个默认参数,那么b.__defaults__[0]就是指向b()的第一个默认参数x。
证据:
def a(): print 'a executed' return []def b(x=a()): print 'id(x):',id(x) x.append(5)for i in range(2): print '*'*20 b() print 'b.__defaults__:',b.__defaults__ print 'id(b.__defaults__[0]):',id(b.__defaults__[0])for i in range(2): print '*'*20 b(list()) print 'b.__defaults__:',b.__defaults__ print 'id(b.__defaults__[0]):',id(b.__defaults__[0])
我们先预测结果:
1、因为默认函数只会在def执行的时候,被计算一次,所以结果应该只有一个:a executed。
2、两个for循环一共4次调用b(),前两次没有传参(那么x就用的是默认参数),后两次传参。
3、因为默认参数一直就这么一个对象,所以两个for循环中四个id(b.__defaults__[0])都是指向同一个id。
4、前两次调用b()中,id(x) == id(b.__defaults__[0]),后两次b()中,id(x)互相不同,且都异于id(b.__defaults__[0])。
实际结果是(完全正确):
a executed********************id(x): 48881992b.__defaults__: ([5],)id(b.__defaults__[0]): 48881992********************id(x): 48881992b.__defaults__: ([5, 5],)id(b.__defaults__[0]): 48881992********************id(x): 48753672b.__defaults__: ([5, 5],)id(b.__defaults__[0]): 48881992********************id(x): 48754056b.__defaults__: ([5, 5],)id(b.__defaults__[0]): 48881992
看来这个list当默认参数值时,还需要特别注意呢。
为了避免类似问题代码的情况,官方文档的写法是:
def foo(a, b=None): if b is None: b = [] b.append(a) print bfoo(1)foo(2)
总结:
1、当list、dic等可变类型作为函数默认参数并且调用函数时没有传参的时候,要注意list、dic并不会自己清空。
2、默认参数只在def语句被执行的时候计算一次。
3、如果想要的话,把默认参数当成静态变量(也就是全局变量)也是一种抖机灵的好思路呢。
参考文献:
官方文档:https://docs.python.org/2.7/tutorial/controlflow.html#default-argument-values
知乎某问题:http://www.zhihu.com/question/21924859
陷阱!python参数默认值:http://segmentfault.com/a/1190000000743526
- python 当list,dic作为默认参数的正确写法
- Python 列表作为默认参数的陷阱
- 当函数作为默认参数的值时
- Python list dic tuple string
- python 按照list中的dic的某key排序
- Python中list、tupe、dic、set的使用小记
- python--可变对象作为默认参数
- python中dic的操作
- python 用list,dic实现switch功能的一个奇葩现象
- java 中以||作为split分隔符正确的写法
- python使用变量作为默认参数时所遇到的奇怪问题
- python获取参数的写法
- python的基本操作(dic)
- python dic与str的相互转化
- 关于Python中dic的一点尝试
- python dic与str的相互转化
- python 中字典(dic)的用法
- python中字典的dic.setdefault()用法
- HDOJ1856More is better (并查集)
- OC循环渐进:自定义通知NSNotification
- Java程序运行机制及运行过程
- (9) Cookie
- 机房收费系统颗粒大归仓之----DTPicker控件与导出数据为Excel
- python 当list,dic作为默认参数的正确写法
- 支持向量机(SVM)中核函数的选择
- jquery源码阅读之jquery.extend
- 什么是Java集合API?
- Android studio运行时乱码 编码问题 閿欒: 缂栫爜UTF-8鐨勪笉鍙槧灏勫瓧绗?
- android PhoneStateListener 内存泄露的问题
- Android XML文件链接错误
- CentOS下安装Git
- 周赛-Toy Cars