0

0

Python 函数参数的默认值为可变对象时需要小心

WBOY

WBOY

发布时间:2023-04-22 13:37:07

|

1418人浏览过

|

来源于51CTO.COM

转载

看到了有给 Python 函数参数的默认值传递可变对象,以此来加快斐波那契函数的递归速度,代码如下:

def fib(n, cache={0: 0, 1: 1}):
if n not in cache:
cache[n] = fib(n - 1) + fib(n - 2)
return cache[n]

是不是很新奇,居然可以这样,速度真的非常快,运行结果如下:

小心此坑:Python 函数参数的默认值是可变对象

不过,我劝你不要这样做,而且 IDE 也会提示你这样做很不好:

小心此坑:Python 函数参数的默认值是可变对象

这是因为,万物皆对象,Python 函数也是对象,参数的默认值就是对象的属性,在编译阶段参数的默认值就已经绑定到该函数,如果是可变对象,Python 函数参数的默认值在会被存储,并被所有的调用者共享,也就是说,一个函数的参数默认值如果是一个可变对象,例如 List、Dict,调用者 A 修改了它,那么之后调用者 B 在调用的时候看到的就是 A 修改后的结果,这样的模式往往会产生意想不到的结果,比如上面 fib 的算法,但更多的是 bug。

可以看下这段简单的代码:

def func(n, li = []):
for i in range(n):
li.append(i)
print(l)

func(2) # [0,1]
func(3,l=[1,2]) # [1,2,0,1,2]
func(2) # [0,1]

你可以先估算一下这段代码的输出,如果和注释中的一样,那你就错了。正确的结果是:

[0, 1]
[1, 2, 0, 1, 2]
[0, 1, 0, 1]

你可能会觉得,最后一个 func(2) 怎么是这样,不急,我们 print(id(li)) 调试一下:

def func(n, li = []):
print(id(li))
for i in range(n):
li.append(i)
print(li)

func(2)
func(3,li=[1,2])
func(2)

结果如下:

140670243756736
[0, 1]
140670265684928
[1, 2, 0, 1, 2]
140670243756736
[0, 1, 0, 1]

有没有发现,第一个 func(2) 和第二个 func(2) 的 id 是一样的,说明它们用到的是 li 是同一个,这就参数的默认值是可变对象的逻辑,对于所有的调用者来讲,是共享的。

Python之模块学习 中文WORD版
Python之模块学习 中文WORD版

本文档主要讲述的是Python之模块学习;python是由一系列的模块组成的,每个模块就是一个py为后缀的文件,同时模块也是一个命名空间,从而避免了变量名称冲突的问题。模块我们就可以理解为lib库,如果需要使用某个模块中的函数或对象,则要导入这个模块才可以使用,除了系统默认的模块(内置函数)不需要导入外。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看

下载

如果要深入研究 Python 为什么这么设计,可以移步 http://cenalulu.github.io/python/default-mutable-arguments/

如何避免?

最好的方式是不要使用可变对象作为函数默认值。如果非要这么用的话,下面是一种解决方案:

def generate_new_list_with(my_list=None, element=None):
if my_list is None:
my_list = []
my_list.append(element)
return my_list

这样,如果 my_list 默认值永远都是 []。

最后

我想那个 fib 函数的实现可能会让你印象深刻,不过请注意,这样的用法非常危险,不可用于自己的代码中。

相关文章

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

22

2026.01.23

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

24

2026.01.23

yy漫画官方登录入口地址合集
yy漫画官方登录入口地址合集

本专题整合了yy漫画入口相关合集,阅读专题下面的文章了解更多详细内容。

99

2026.01.23

漫蛙最新入口地址汇总2026
漫蛙最新入口地址汇总2026

本专题整合了漫蛙最新入口地址大全,阅读专题下面的文章了解更多详细内容。

132

2026.01.23

C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

15

2026.01.23

php远程文件教程合集
php远程文件教程合集

本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

65

2026.01.22

PHP后端开发相关内容汇总
PHP后端开发相关内容汇总

本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

61

2026.01.22

php会话教程合集
php会话教程合集

本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

63

2026.01.22

宝塔PHP8.4相关教程汇总
宝塔PHP8.4相关教程汇总

本专题整合了宝塔PHP8.4相关教程,阅读专题下面的文章了解更多详细内容。

33

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 19.6万人学习

Django 教程
Django 教程

共28课时 | 3.5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号