python的函数定义中99%的人会遇到的一个坑
列表是一种经常使用的数据类型。在函数的定义中,常常会使用列表作为参数。
比如,要测试一个接口的数据,接口返回的数据格式如下:
{
"code": "20000",
"data": ["孙悟空","李白","甄姬"],
"msg": "success",
"status": 0
}
要测试的内容是:返回的 data 数据是否跟需求符合。在测试之前,需要对数据进一步处理,比如要增加 “王昭君” 这个元素进去,需要写一个函数:
def add_element(data=["孙悟空","李白","甄姬"]):
data.append('王昭君')
return data
print(add_element())
print(add_element())
print(add_element())
在函数定义的时候经常会给参数设置默认值,在这个例子中,将 data 参数设置了默认值,函数定义以后,后面会被频繁的调用,期望值应该是打印如下:
["孙悟空","李白","甄姬","王昭君"]
["孙悟空","李白","甄姬","王昭君"]
["孙悟空","李白","甄姬","王昭君"]
实际结果为:
["孙悟空","李白","甄姬","王昭君"]
["孙悟空","李白","甄姬","王昭君","王昭君"]
["孙悟空","李白","甄姬","王昭君","王昭君","王昭君"]
原因
当定义函数时,会保存函数中默认参数 data 的值,也就是 ["孙悟空","李白","甄姬"]
,在每次调用的时候如果传递了新的实参,则使用传递的参数;没有传递,使用定义函数时保存的默认参数。
上面两次调用中,都没有传递新的实参,程序会调用定义函数时保存的默认参数,因为 append() , 在第一次调用以后,默认参数已经由 ["孙悟空","李白","甄姬"]
改变为 ["孙悟空","李白","甄姬","王昭君"]
,再次执行 append() 之后,就变成了 ["孙悟空","李白","甄姬","王昭君","王昭君"]
;同理,第三次又改变了。
可以使用 id() 函数来定位问题:
def add_element(data=["孙悟空","李白","甄姬"]):
# id 来表示是不是同一个对象
print(id(data))
data.append('王昭君')
return data
print(add_element())
print(add_element())
print(add_element())
打印出来的 id(data)
为同一个对象,也就是默认参数。如果我们改变 第二个 print(add_element())
为 print(add_element(["孙悟空","李白","甄姬"]))
,那么第 2 个 id(data)
就会发生变化,因为它不在是默认值,而是新传进来的实参,实际结果也将变成:
2543416926792
['孙悟空', '李白', '甄姬', '王昭君']
2543418907848
["孙悟空","李白","甄姬", '王昭君']
2543416926792
['孙悟空', '李白', '甄姬', '王昭君', '王昭君']
改进方案
- 如果参数中有列表,尽量不要用它做默认参数
- 如果使用了列表作为默认参数,函数调用时传入实参,而不是省略
- 可以在函数体中另外定义一个变量接收默认参数
def add_element(data=["孙悟空","李白","甄姬"]):
if data == ["孙悟空","李白","甄姬"]:
data = ["孙悟空","李白","甄姬"]
data.append('王昭君')
return data
python的函数定义中99%的人会遇到的一个坑的更多相关文章
- python函数定义中引用外部变量的一个问题
如果在函数定义的默认值中引用了一个外部变量,如下所示 x = 3 def func(a = x): print(a, x) 那么a的默认值就会是3, 但是print语句中的x会是调用时的x值 lamb ...
- 关于Python中正则使用findall和分组的一个坑
版权声明:本文为sam的原创文章,转载请添加出处:http://blog.csdn.net/samed https://blog.csdn.net/samed/article/details/5055 ...
- [Python]Python Class 中的 函数定义中的 self
In [80]: class MyClass001: ....: def selfDemo(self): ....: print 'My Demo' ....: In [81]: p = MyClas ...
- Python:函数定义
#!/usr/bin/python3 #函数 def add(a,b): return a+b print("add(2,5) = ",add(2,5)) def add2(a,b ...
- java中变量命名和引用变量的一个坑
这次有两个主题,第一个太简单啦,就是java中变量的命名规则,纯记忆性东西.第二个主题,就是讨论一下对象引用变量的一个注意点.
- js中window对象的opener属性的一个坑
2018-05-08 17:48:33 今天我编写代码碰到了一个让我纠结了很久的坑,特别想在此说一下,让其他人避免我踏过的这个坑. 这个坑就是:在我自己写的子窗口中用opener属性却获取不到父窗口的 ...
- 在模态框(Modal)中使用UEditor全屏显示的一个坑
根据这个问题很简单就能查到一些文章明确说明了解决问题的方法,就是如下一段代码: var isModal = false; //判断该dom是否为modal var classes = $(contai ...
- Java中对象JSON格式化处理时的一个坑
在项目中遇到了一个JSON的坑.记录下. 直接上代码: import java.util.ArrayList; import com.alibaba.fastjson.JSON; public cla ...
- python中函数定义之实参、形参
一般在函数的定义中,会有一类变量---形参,它是函数完成其工作的一项信息.实参往往是调用函数时传递给函数的信息.我们在调用函数时,将要让函数使用的信息放在括号内.例如定义一个函数def greet_u ...
随机推荐
- [洛谷P3377]【模板】左偏树(可并堆)
题目大意:有$n$个数,$m$个操作: $1\;x\;y:$把第$x$个数和第$y$个数所在的小根堆合并 $2\;x:$输出第$x$个数所在的堆的最小值 题解:左偏树,保证每个的左儿子的距离大于右儿子 ...
- 周记【距gdoi:117天】
国庆被“吞”了 图论还剩下平面图.分层图.欧拉图…… 是现实太残酷还是自己兴趣不够? 努力吧.
- Divljak
Divljak Alice 有 $n$ 个字符串 $ S_1,S_2,\cdots,S_n $ ,Bob有一个字符串集合 $T$ ,一开始集合是空的. 接下来会发生 $q$ 个操作,操作有两种形式: ...
- 【HDU 4300 Clairewd’s message】
Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important ...
- ContestHunter#17-C 舞动的夜晚
Description: L公司和H公司举办了一次联谊晚会.晚会上,L公司的N位员工和H公司的M位员工打算进行一场交际舞.在这些领导中,一些L公司的员工和H公司的员工之间是互相认识的,这样的认识关系一 ...
- 如何设置项目encoding为utf-8
1.鼠标右键点击项目,选择[properties] 2.选择[Resource],在Text file encoding里面选择UTF-8,点击[ok] 大功告成! 木头大哥所发的文章均基于自身实践, ...
- [POI2006] OKR-period of words
传送门 - > \(bzoj 1511\) 题目描述 A string is a finite sequence of lower-case (non-capital) letters of t ...
- 自己实现的JDBC工具类
最近做了个后台应用程序,刚开始用Spring+iBatis来做的,后来因为种种原因,不让用Spring.iBatis以及一些开源的工具包. 于是用JDBC重写了原来的Service实现,项目做完了 ...
- Sencha touch中Ext.List的使用及高度自适应
最近在做 Sencha 的一个项目,需要用到 Ext.List 来列出所需商品及相关信息,平时我们使用 Ext.List 都是使用 fullscreen:true 来设置 List 全屏显示, 但 ...
- Java并发(7)- 你真的了解ReentrantReadWriteLock吗?
引言 在前几篇文章中了解了ReentrantLock.Semaphore与CountDownLatch后,J.U.C包中基于AQS实现的并发工具类还剩一个比较重要的:读写锁ReentrantReadW ...