关于Python中函数默认参数的研究
来源:互联网 发布:excel找出重复数据 编辑:程序博客网 时间:2024/06/06 01:26
源于对一个项目的bug,调试,一直出现的问题就是,在本地运行没有问题,但是,一旦上线,就会出现问题,同样相似的在下面的例子里面也出现这样的情况。
代码:
def foo(bar=[]): bar.append('abc') return barif __name__ == '__main__': print foo()
在linux下,运行
[root@kvm_10_112_117_88 /data/flyfly]# python param.py
[‘abc’]
[root@kvm_10_112_117_88 /data/flyfly]# python param.py
[‘abc’]
[root@kvm_10_112_117_88 /data/flyfly]# python param.py
[‘abc’]
[root@kvm_10_112_117_88 /data/flyfly]# python param.py
[‘abc’]
都没有问题,
然而,在Python解释器中
>>> def foo(bar=[]):... bar.append('abc')... return bar...
运行
>>> foo()['abc']>>> foo()['abc', 'abc']>>> foo()['abc', 'abc', 'abc']
完全不能忍呀
这是为啥呢
先看看 Python中的默认参数是如何实现的,或者说,对于一个可变变量作为默认参数时,会发生什么
Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call.
在这篇文章https://segmentfault.com/a/1190000000743526中有详细讲到这个问题,也就是默认参数一次执行多次调用
为了研究Python中默认参数的运行机制,利用下面的代码进行测试
首先
def a(): print "a executed" return []def b(x=a()): print "id(x): ", id(x) x.append(5) print "x: ", x
运行结果
a executed
也就是在定义函数时,默认函数被复制,被执行,
增加如下代码
def a(): print "a executed" return []def b(x=a()): print "id(x): ", id(x) x.append(5) print "x: ", xfor i in range(2): print "-" * 15, "Call b()", "-" * 15 b() print b.__defaults__ print "id(b.__defaults__[0]): ", id(b.__defaults__[0])
运行结果
a executed
————— Call b() —————
id(x): 14226712
x: [5]
([5],)
id(b.defaults[0]): 14226712
————— Call b() —————
id(x): 14226712
x: [5, 5]
([5, 5],)
id(b.defaults[0]): 14226712
这里面看到,虽然多次调用b()函数,但是并不是每次都初始化里面的默认参数,两者使用的是同一个地址
修改代码
def a(): print "a executed" return []def b(x=a()): print "id(x): ", id(x) x.append(5) print "x: ", xfor i in range(2): print "-" * 15, "Call b(list())", "-" * 15 b(list()) print b.__defaults__ print "id(b.__defaults__[0]): ", id(b.__defaults__[0])
结果
a executed
————— Call b(list()) —————
id(x): 34693920
x: [5]
([],)
id(b.defaults[0]): 34620696
————— Call b(list()) —————
id(x): 34693992
x: [5]
([],)
id(b.defaults[0]): 34620696
这里面每次都重新定义了一个list,所以不会是相同的地址
所以如果默认参数是一个可变变量,这时就会出现问题,
对于本文一开始出现的现象,每次运行Python之后其生命周期就会结束,而在Python解释器中,其生命周期会一直保持,所以才会出现这样的情况。
- 关于Python中函数默认参数的研究
- Python函数的默认参数
- 学习Python中关于默认参数的理解
- python函数中使用默认参数的坑
- C++中关于默认构造函数和默认参数…
- python 函数默认参数的问题
- 谈谈Python函数的默认参数
- python的默认参数和可变对象研究
- python中函数默认参数的陷阱(《改善python程序的91个建议》)
- 关于python 的函数默认参数与关键字keyword的想法
- Python中默认参数self的理解
- Python中默认参数self的理解
- Python中默认参数self的理解
- Python 函数的默认参数, 关键字参数的调用
- C++中函数的默认参数
- C++中函数的默认参数
- c++中函数的默认参数(5)
- Python split()函数默认参数
- 双向循环链表-模板-自定义类型
- 记录
- 《JAVA并发编程实战》 - 原子变量与非阻塞同步机制
- PAT L2-012. 关于堆的判断(最小堆调整)
- PSCC2015及AdobeCC2015全套安装及破解
- 关于Python中函数默认参数的研究
- php面向对象(OOP)编程教程
- 接口类与抽象类的实际作用
- No.1-0-0 从今天起努力更新
- error CS0117: `System.IO.File' does not contain a definition for `WriteAllBytes'
- Android——初识RxJava
- 第一篇博文
- Divide Two Integers
- 《java并发编程实战》 - java内存模型