Chinaunix首页 | 论坛 | 博客
  • 博客访问: 417345
  • 博文数量: 72
  • 博客积分: 2541
  • 博客等级: 少校
  • 技术积分: 756
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-20 16:08
文章分类

全部博文(72)

文章存档

2013年(13)

2009年(1)

2008年(7)

2007年(45)

2006年(6)

我的朋友

分类: Python/Ruby

2013-06-20 13:49:23

函数的缺省参数值(Default Argument Values)

By Harrison Feng

我们在Python里写函数时,常常会给一些参数赋初始值。我们把这些初始值叫作Default Argument Values
一般情况下,我们可以很自由的给参数赋初值,而不需要考虑任何异常的情况或者陷阱。但是当你给这些参数
赋值为可变对象(
mutable object),比如listdictionary,很多类的实例时,那么你要小心了,因为函数参数
的初值只能被计算一次(在函数定义的时间里)。怎么来理解呢?我们来看下面的例子。

  1. def bad_foo(item, my_list=[]):
  2.     my_list.append(item)
  3.     return my_list

  4. print bad_foo('a')

  5. print bad_foo('b')

  6. print bad_foo('c')
输出结果:

  1. ['a']
  2. ['a', 'b']
  3. ['a', 'b', 'c']
按我们常规的理解,上面的输出结果应该是['a']['b']['c'],而不是['a']['a', 'b']['a', 'b', 'c']。难道解释器
有问题?答案是解释器的输出结果完全正确。由于前面我们说了函数参数的初值只会在函数定义的时间里计
算一次。所以,你在第二次调用函数时,
my_list=[]不会再被执行,此时my_list已经不在等于[],而是等于
['a'],以此类推。

为了看清本质,我们将上面的代码改一下,在操作my_list之前,我们先输出my_list。代码如下:
  1. >>> def bad_foo(item, my_list=[]):
  2.                print my_list
  3.                my_list.append(item)
  4.                return my_list

  5. >>> bad_foo('a')
  6. []
  7. ['a']
  8. >>> bad_foo('b')
  9. ['a']
  10. ['a', 'b']
  11. >>> bad_foo('c')
  12. ['a', 'b']
  13. ['a', 'b', 'c']
哇喔,是不是很神奇?

既然会出现这样的小陷阱,那么我们怎么来避免呢?下面的代码将消除这个小陷阱。
  1. >>> def good_foo(item, my_list=None):
  2.                if my_list is None:
  3.                       my_list=[]
  4.                my_list.append(item)
  5.                return my_list

  6. >>> good_foo('a')
  7. ['a']
  8. >>> good_foo('b')
  9. ['b']
  10. >>> good_foo('c')
  11. ['c']
  12. >>>
我们也可以用同样的方法来查看my_list在被操操作之前和之后的值。
  1. >>> def good_foo(item, my_list=None):
  2.                print my_list
  3.                if my_list is None:
  4.                       my_list=[]
  5.                print my_list
  6.                my_list.append(item)
  7.                return my_list

  8. >>> good_foo('a')
  9. None
  10. []
  11. ['a']
  12. >>> good_foo('b')
  13. None
  14. []
  15. ['b']
  16. >>> good_foo('c')
  17. None
  18. []
  19. ['c']
当然,我们也可以给my_list赋可变对象,然后将my_list在使用之前初始化。代码如下:
  1. >>> def good_foo(item, my_list=[]):
  2.                print my_list
  3.                if my_list:
  4.                       my_list=[]
  5.                print my_list
  6.                my_list.append(item)
  7.                return my_list

  8. >>>
  9. >>> good_foo('a')
  10. []
  11. []
  12. ['a']
  13. >>> good_foo('b')
  14. ['a']
  15. []
  16. ['b']
  17. >>> good_foo('c')
  18. ['a']
  19. []
  20. ['c']
  21. >>>
个人还是建议用第一种good_foo的方法。
所以,当我们想要给函数参数的初始化为可变对象时,我们要注意到这一点。
阅读(900) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~