返回介绍

建议32:警惕默认参数潜在的问题

发布于 2024-01-30 22:19:09 字数 1591 浏览 0 评论 0 收藏 0

默认参数可以给函数的使用带来很大的灵活性,当函数调用没有指定与形参对应的实参时就会自动使用默认参数。

>>> def appendtest(newitem,lista = []):        #
默认参数为空列表
...  print id(lista)
...  lista.append(newitem)
...  print id(lista)
...  return lista
...
>>>
>>> appendtest('a',['b',2,4,[1,2]])
39644216
39644216
['b', 2, 4, [1, 2], 'a']
>>>

现在请读者思考这么一个问题:如果第二个参数采取默认参数,连续调用两次appendtest(1)、appendtest('a'),函数的返回值是多少?期望的结果应该是[1]和['a'],对吧?可是实际情况却输出了[1]和[1, 'a']。那么这是什么原因呢?

def在Python中是一个可执行的语句,当解释器执行def的时候,默认参数也会被计算,并存在函数的.func_defaults属性中。由于Python中函数参数传递的是对象,可变对象在调用者和被调用者之间共享,因此当首次调用appendtest(1)的时候,[]变为[1],而再次调用的时候由于默认参数不会重新计算,在[1]的基础上便变为了[1,'a']。我们可以通过查看函数的func_defaults来确认这一点。

>>> appendtest(1)
39022960
39022960
[1]
>>> appendtest.func_defaults           #
第一次调用后默认参数变为[1]
([1],)
>>> appendtest('a')
39022960
39022960
[1, 'a']
>>> appendtest.func_defaults
           #
经过第二次调用 
变为[1,
’a
’]
([1, 'a'],)
>>>
>>> appendtest.func_defaults[0][:] = []
      #
可以直接修改func_defaults
属性
>>> appendtest.func_defaults
([],)

如果不想让默认参数所指向的对象在所有的函数调用中被共享,而是在函数调用的过程中动态生成,可以在定义的时候使用None对象作为占位符。因此本节开头的例子应该修正为如下形式:

>>> def appendtest(newitem,lista = None):#
默认参数改为None
...  if lista is None:
...      lista = []
...  lista.append(newitem)
...  return lista
...

最后以一个问题结束本节:假设report()函数需要传入当前系统的时间并做一些处理,下面两种参数传递方式哪种正确呢?读者应该知道答案了!

>>> import time
>>> def report(when = time.time()):
...  pass
...
>>> def report(when = time.time):
...  pass
...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文