永远不要使用 Python 的可变值作为默认值
丹尼尔·陶西斯在 Unsplash 上的照片
会发生什么,为什么会发生,怎么做才能避免。
可变违约的后果
我们编写了一个函数,它将学生的姓名和分数作为参数,并根据提供的分数将“通过”或“未通过”添加到字典中。为了方便起见,由用户决定她是否要提供字典。如果她不做,我们想重新开始。我们的第一次尝试是这样的:
这看起来不错,但是让我们在不提供字典的情况下连续使用这个函数两次,看看会发生什么:
从输出中可以看到,每个函数调用都将 指向同一个对象 。这不是我们想要发生的!
重复使用对象的原因
让我们来搞清楚这种行为。如果我们试图访问函数外部的变量,Python 会返回一个 NameError 。这表明变量作用域按预期工作。然而,该值必须在某处可用;否则,Python 无法在第二次函数调用期间添加键。
让我们再深入一层。下面是同一函数的调整版本,它也返回字典的 内存地址:
如果我们查看结果,我们可以看到两个调用都引用了内存中的同一个对象。我们也能够直接从内存中提取值。总之,我们不能通过变量访问这个值,但是它在内存中是安全可靠的。那么, 让它活下去的隐藏引用 在哪里呢?
答案在于 Python 加载函数的方式。也就是说,每当 Python 第一次加载一个函数时,它也会创建对其默认值的 引用。也就是说,对函数的引用隐藏了对字典的引用。
如何防止这种行为
为了防止这种不必要的行为,我们需要将引用的创建转移到函数本身中。这确保了每个函数调用都使用新的引用而不是旧的引用。修改后的函数如下所示:
如您所见,现在每个函数调用都指向另一个内存地址。这些对象不再相互干扰。这是一个针对较小主题的新“快速修复”格式的实验。让我知道你对它的看法,在评论中或者在推特上。我也很乐意在 LinkedIn 上联系。感谢您的阅读!
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论