Python中如何避免默认参数的陷阱

 更新时间:2025年01月23日 16:16:15   作者:云墨-款哥的博客  
在 Python 中,我们经常会使用函数的默认参数来简化代码,但你知道吗默认参数的行为有时可能会导致一些难以察觉的错误,下面小编就为大家介绍一下如何避免这样的错误吧

在 Python 中,我们经常会使用函数的默认参数来简化代码。但你知道吗?默认参数的行为有时可能会导致一些难以察觉的错误,尤其是当默认参数是一个可变对象(如列表或字典)时。今天,我们就来探讨一下这个问题,并学习如何避免它。

问题背景

我们通常会定义一个函数,并为其提供一些默认参数。例如:

def test(a, lst=[1, 2]):
    """
    给列表添加元素
    :param a: 需要添加的元素
    :param lst: 需要添加元素的列表
    :return: 添加之后的列表
    """
    if a not in lst:
        lst.append(a)
    return lst
print(test(4)) # [1, 2, 4]
print(test(40)) # [1, 2, 40],实际输出:[1, 2, 4, 40]
print(test(40, lst=[])) # [40]
print(test(80)) # 实际输出:[1, 2, 4, 40, 80]

我们在定义函数的时候,创建的默认参数lst,会在内存中创建一块存储区域用来存放这个列表

当我们第一次调用的时候,由于列表是可变类型,我们修改的是实际的值,但是我们的映射地址没有变

这个时候该地址对应的数据就发生了变化

当我们给这个lst传值得时候,相当于我们又新开了一块内存,来储存这个新的列表,这时候会生成一个新的地址

固当我们再次使用test(80)调用的时候,操作的仍是初始创建的列表

这个函数的目的是:接收一个参数 a,然后将其添加到列表 lst 中。如果 a 不在列表中,就将它添加进去并返回修改后的列表。

我们来看一下这个代码的执行过程。

默认参数的行为

在 Python 中,函数的默认参数值是 在函数定义时就计算并初始化的。这意味着,默认参数 lst=[1, 2] 只会在函数首次定义时创建一次,而不是每次调用函数时都会重新创建。如果你修改了默认参数中的可变对象(比如列表、字典等),下次调用函数时这个对象会被“记住”。

示例分析

print(test(4))  # [1, 2, 4]
print(test(40))  # [1, 2, 4, 40]
print(test(40, lst=[]))  # [40]
print(test(80))  # [1, 2, 4, 40, 80]

第一行: 调用 test(4) 时,lst 使用了默认参数 [1, 2],因此 4 被成功地添加到了列表中,返回 [1, 2, 4]。

第二行: 调用 test(40) 时,由于默认参数 lst 被修改过了,变成了 [1, 2, 4],因此 40 被加入到了列表中,返回 [1, 2, 4, 40]。

第三行: 调用 test(40, lst=[]) 时,你明确传入了一个新的空列表 [],因此返回的是新的列表 [40],不会受到前面修改的影响。

第四行: 再次调用 test(80) 时,lst 已经被修改为 [1, 2, 4, 40],因此 80 被添加到列表中,最终返回 [1, 2, 4, 40, 80]。

问题的根源

问题的根源在于:默认参数是共享的。当你修改了默认参数(如列表、字典等可变对象)时,这些修改会影响到后续的函数调用。

在上面的代码中,默认列表 lst 是可变的,每次调用函数时都会操作同一个列表,从而导致了不可预期的结果。

如何避免默认参数引发的问题?

为了避免默认参数引发的问题,我们可以使用 None 作为默认参数,并在函数内部检查参数是否为 None,如果是,则创建一个新的列表。修改后的代码如下:

def test(a, lst=None):
    if lst is None:
        lst = [1, 2]  # 创建新的列表
    if a not in lst:
        lst.append(a)
    return lst

这种做法能够确保每次调用 test 函数时,都使用一个全新的列表,而不会出现共享默认参数的问题。

总结

在 Python 中,默认参数如果是可变对象(如列表、字典等),则它们的修改会影响到后续的调用。这种行为可能导致一些难以察觉的错误。为了解决这个问题,我们可以将默认参数设置为 None,然后在函数内部根据需要创建新的对象。这是避免共享可变对象的经典做法。

到此这篇关于Python中如何避免默认参数的陷阱的文章就介绍到这了,更多相关Python默认参数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python之批量创建文件的实例讲解

    Python之批量创建文件的实例讲解

    今天小编就为大家分享一篇Python之批量创建文件的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • Python爬取qq music中的音乐url及批量下载

    Python爬取qq music中的音乐url及批量下载

    这篇文章主要给大家介绍了利用Python爬取qq music中的音乐url及实现批量下载的相关资料,文中给出了详细的介绍和示例代码,相信对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
    2017-03-03
  • Pandas提取单元格的值操作

    Pandas提取单元格的值操作

    这篇文章主要介绍了Pandas提取单元格的值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • 浅析Python中的多重继承

    浅析Python中的多重继承

    这篇文章主要介绍了Python中的多重继承,是Python学习中的基本知识,代码基于Python2.x版本,需要的朋友可以参考下
    2015-04-04
  • Python字符串对象实现原理详解

    Python字符串对象实现原理详解

    这篇文章主要介绍了Python字符串对象实现原理详解,在Python世界中将对象分为两种:一种是定长对象,比如整数,整数对象定义的时候就能确定它所占用的内存空间大小,另一种是变长对象,在对象定义时并不知道是多少,需要的朋友可以参考下
    2019-07-07
  • python pygame实现2048游戏

    python pygame实现2048游戏

    这篇文章主要为大家详细介绍了python pygame实现2048游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • 基于keras输出中间层结果的2种实现方式

    基于keras输出中间层结果的2种实现方式

    今天小编就为大家分享一篇基于keras输出中间层结果的2种实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • 详解Python IO编程

    详解Python IO编程

    这篇文章主要介绍了Python IO编程的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • Python实现学校管理系统

    Python实现学校管理系统

    这篇文章主要为大家详细介绍了Python实现学校管理系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • 如何基于Python批量下载音乐

    如何基于Python批量下载音乐

    这篇文章主要介绍了如何基于Python批量下载音乐,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11

最新评论