在Python函数中,传递的参数如果默认有一个为 列表(list),那么就要注意了,此处有坑!!
入坑
def f(x,li=[]):
for i in range(x):
li.append(i*i)
print(li)
print('---1---')
f(4)
print('---2---')
f(5)
预期结果
---1---
[0, 1, 4, 9]
---2---
[0, 1, 4, 9, 16]
执行结果
---1---
[0, 1, 4, 9]
---2---
[0, 1, 4, 9, 0, 1, 4, 9, 16]
出坑
当定义函数时,会保存函数中默认参数 list的值,也就是列表 li=[];
在每次调用的时候如果传递了新的列表,则使用传递的列表,没有传递,使用定义函数时保存的默认参数(li=[]);
上面两次调用中,都没有传递新的列表(使用默认列表 li=[] ),程序会调用定义函数时保存的默认参数((li=[]));
列表在append的时候会在 li=[] 原来的基础上append追加值,所以会产生以上结果.
通过打印列表的ID进行辨识
打印列表 li=[] 的ID:
def f(x,li=[]):
print(id(li)) # 添加打印id
for i in range(x):
li.append(i*i)
print(li)
print('---1---')
f(4)
print('---2---')
f(5)
结果:
---1---
140306123906248
[0, 1, 4, 9]
---2---
140306123906248
[0, 1, 4, 9, 0, 1, 4, 9, 16]
会发现ID值是相同的;
说明两次执行时使用的都是定义函数时的默认参数 li=[ ]
执行时往里面传新的列表
打印列表 li=[] 的ID 和 传的新列表的ID:
def f(x,li=[]):
print(id(li))
for i in range(x):
li.append(i*i)
print(li)
print('---1---')
f(4)
print('---2---')
f(5,[])
print('---3---')
f(6)
结果:
---1---
[0, 1, 4, 9]
---2---
[0, 1, 4, 9, 16]
---3---
[0, 1, 4, 9, 0, 1, 4, 9, 16, 25]
会发现执行传递空(新)列表的函数时打印的ID不一样,而没有传递的一样;
当传递空列表时,函数体当中会使用传递的空列表,没有传递时,使用函数默认值 li=[ ], 所以会产生以上结果。
优化
如果想要达到预期的结果,只需要在函数体里进行判断即可:
def f(x, li=[]):
if not li:
# 如果li不为空的话,就往下走(清空列表); 为空就不走
li = []
for i in range(x):
li.append(i * i)
print(li)
print('---1---')
f(4)
print('---2---')
f(5)
print('---3---')
f(6)
结果:
---1---
[0, 1, 4, 9]
---2---
[0, 1, 4, 9, 16]
---3---
[0, 1, 4, 9, 16, 25]
Python之在函数中使用列表作为默认参数
本文将介绍笔者在工作中遇到的Python的一个坑,那就是使用列表作为默认参数. 我们知道,在Python中,列表(list)是可变对象,所以列表的内容可能会在函数内改变.另一个需要注意的是,使 ...
Python函数中的列表
在看21天的Python书中写出了一个陷阱,但没给出解释,以下为代码陷阱
python函数中的位置参数、默认参数、关键字参数、可变参数区别
一.位置参数 调用函数时根据函数定义的参数位置来传递参数. #!/usr/bin/env python # coding=utf-8 def print_hello(name, sex): sex_d ...
Python 函数中,参数是传值,还是传引用?
在 C/C++ 中,传值和传引用是函数参数传递的两种方式,在Python中参数是如何传递的?回答这个问题前,不如先来看两段代码. 代码段1: def foo(arg): arg = 2 print(a ...
Python函数中参数类型
在学习Python函数的时候,函数本身的定义和调用并不是很复杂,但是函数的参数类型和用法的确有些复杂.在此做一个小结,加深理解. Python参数的定义 负责给函数提供一些必要的数据或信息,以保证函数 ...
Python函数中的可变参数
在Python函数中,还可以定义可变参数. 如:给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……. 要定义出这个函数,我们必须确定输入的参数.由于参数个数不确定,我们首先想到可以把 ...
python函数中的参数类型
python函数中的参数 动态获取函数的参数 python的函数类型详解
一道题带你搞定Python函数中形参和实参问题
昨天在Python学习群里有位路人甲问了个Python函数中关于形参和实参一个很基础的问题,虽然很基础,但是对于很多小白来说不一定简单,反而会被搞得稀里糊涂.人生苦短,我用Python. 为了解答大家 ...
python 函数中使用全局变量
python 函数中如果需要使用全局变量,需要使用 global + 变量名 进行声明, 如果不声明,那么就是重新定义一个局部变量,并不会改变全局变量的值 n [1]: a = 3 In [2]: d ...
随机推荐
Sublime Text 3编译Sass - Sublime Text安装Sass插件
1.首先要安装sass,安装流程: http://www.w3cplus.com/sassguide/install.html 2.sublime text安装Package Control(已经安装 ...
User mode and kernel mode
[User mode and kernel mode] 参考:https://msdn.microsoft.com/en-us/library/windows/hardware/ff554836(v= ...
Python 删除目录中特定文件
代码如下,使用了递归: import sys currDir = sys.path[] import os def removeFile(dir,postfix): if os.path.isdir( ...
js文件内部导入引用js文件方法
function include(path){ var a=document.createElement("script"); a.type = "te ...
为什么 API 监控对于任何业务来说都重要?
对于商务运算来说一个比较稳定的趋势在于对 API 日渐增长的依赖性,几乎每一个代码级交互过程都会调用 API 来收集数据或触发某些关键过程.没有 API ,你将无法与同伴进行文件交流,没有 API , ...
继承Thread类和实现Runnable接口
一.采用继承Thread类方法的特点: 优势:编写简单,如果需要访问当前的线程,只需要使用this,并可以在run()方法中调用其他线程的方法: 劣势:线程已经继承了Thread类,不能继承其他的父类 ...
elk-filebeat-(效果图示)(四)
一.vim filebeat-6.3.2-linux-x86_64/filebeat.yml - type: log # Change to true to enable this input con ...
JAVA记录-SpringMVC集成redis
1.redis.properties #主机地址 redis.host=127.0.0.1 #端口号 redis.port=6379 #当池内没有返回对象时,最大等待时间毫秒数 redis.pool. ...
java字符串分解 StringTokenizer用法
Java中substring方法可以分解字符串,返回的是原字符串的一个子字符串.如果要讲一个字符串分解为一个一个的单词或者标记,StringTokenizer可以帮你. 先看个例子: 1 public ...
长大Tips
队名:CW 队员: B20150304403 王香辉 B20150304408 李孟君 B20150304411 曾翡 B20150304414 吴海波 B20150304430 文淼 B201503 ...