默认参数必须指向不变对象!
2017-07-19 20:53
309 查看
python设置默认参数有个最大的坑,演示如下:
先定义一个函数,传入一个list,添加一个
当你正常调用时,结果似乎不错:
当你使用默认参数调用时,一开始结果也是对的:
但是,再次调用
默认参数是
原因解释如下:
Python函数在定义的时候,默认参数
所以,定义默认参数要牢记一点:默认参数必须指向不变对象!
要修改上面的例子,我们可以用
现在,无论调用多少次,都不会有问题:
为什么要设计
因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
先定义一个函数,传入一个list,添加一个
END再返回:
def add_end(L=[]): L.append('END') return L
当你正常调用时,结果似乎不错:
>>> add_end([1, 2, 3]) [1, 2, 3, 'END'] >>> add_end(['x', 'y', 'z']) ['x', 'y', 'z', 'END']
当你使用默认参数调用时,一开始结果也是对的:
>>> add_end() ['END']
但是,再次调用
add_end()时,结果就不对了:
>>> add_end() ['END', 'END'] >>> add_end() ['END', 'END', 'END']
默认参数是
[],但是函数似乎每次都“记住了”上次添加了
'END'后的list。
原因解释如下:
Python函数在定义的时候,默认参数
L的值就被计算出来了,即
[],因为默认参数
L也是一个变量,它指向对象
[],每次调用该函数,如果改变了
L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的
[]了。
所以,定义默认参数要牢记一点:默认参数必须指向不变对象!
要修改上面的例子,我们可以用
None这个不变对象来实现:
def add_end(L=None): if L is None: L = [] L.append('END') return L
现在,无论调用多少次,都不会有问题:
>>> add_end() ['END']>>> add_end() ['END']
为什么要设计
str、
None这样的不变对象呢?
因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
相关文章推荐
- Python的坑(7) -- 定义默认参数要牢记一点:默认参数必须指向不变对象!
- function (规定参数必须为某个对象的实例)
- Integer等默认对象作函数参数时,亦是传值而非传址
- XFIRE 客户端 传递参数是对象 传递参数的对象所在包路径必须和服务端包路径一样。不然就出现传递过去对象值为空。
- javascript让setInteval里的函数参数中的this指向特定的对象
- python核心编程-默认函数对象参数
- 重载operator<<运算符时第二个参数最好不要写成指向对象的指针
- javascript 中的 prototype和constructor属性的使用(constructor属性始终指向创建当前对象的构造函数,每个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数)
- jquery改变iframe的src,但是jquery获取的这个iframe对象指向的还是默认的
- Builder模式中,为什么必须在对象域而不是builder域中检查参数?
- 基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------> 可以返回派生类对象的引用或指针
- 辛星浅谈PHP中的函数的默认参数必须在右边吗
- C++析构函数的自动调用(析构函数必须是虚拟的,这样删除父类指针指向的子类对象,才能同时调用两者的析构函数,否则就没有机会调用子类析构函数)
- B继承自A,A指针无法隐式转换为B指针,函数参数只管指针类型,与实际指向对象无关
- python函数--默认参数指向不可变对象
- 建立一个对象数组,内放5个学生的数据(学号,成绩),用指向对象的指针做函数参数,在max函数中找出5个学生中成绩最高者,并输出其学号。
- Python 函数默认参数不能使用可变对象,如List,dict
- 为什么Java反射对象必须有一个无参数的构造方法?
- 辛星浅谈PHP中的函数的默认参数必须在右边吗
- 项目访问index.html,默认跳转到login.jsp页面,隐藏地址栏每次显示请求路径和参数,定个在域名不变