在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函数中把列表(list)当参数时的"入坑"与"出坑"的更多相关文章

  1. Python之在函数中使用列表作为默认参数

      本文将介绍笔者在工作中遇到的Python的一个坑,那就是使用列表作为默认参数.   我们知道,在Python中,列表(list)是可变对象,所以列表的内容可能会在函数内改变.另一个需要注意的是,使 ...

  2. Python在函数中使用列表作为默认参数

    在学习中遇到的Python的一个坑,那就是使用列表作为默认参数. 我们知道,在Python中,列表(list)是可变对象,所以列表的内容可能会在函数内改变.另一个需要注意的是,使用列表作为函数的默认参 ...

  3. Python函数中的列表

    在看21天的Python书中写出了一个陷阱,但没给出解释,以下为代码陷阱

  4. python函数中的位置参数、默认参数、关键字参数、可变参数区别

    一.位置参数 调用函数时根据函数定义的参数位置来传递参数. #!/usr/bin/env python # coding=utf-8 def print_hello(name, sex): sex_d ...

  5. Python 函数中,参数是传值,还是传引用?

    在 C/C++ 中,传值和传引用是函数参数传递的两种方式,在Python中参数是如何传递的?回答这个问题前,不如先来看两段代码. 代码段1: def foo(arg): arg = 2 print(a ...

  6. Python函数中参数类型

    在学习Python函数的时候,函数本身的定义和调用并不是很复杂,但是函数的参数类型和用法的确有些复杂.在此做一个小结,加深理解. Python参数的定义 负责给函数提供一些必要的数据或信息,以保证函数 ...

  7. Python函数中的可变参数

    在Python函数中,还可以定义可变参数. 如:给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……. 要定义出这个函数,我们必须确定输入的参数.由于参数个数不确定,我们首先想到可以把 ...

  8. python函数中的参数类型

    python函数中的参数 动态获取函数的参数 python的函数类型详解

  9. 一道题带你搞定Python函数中形参和实参问题

    昨天在Python学习群里有位路人甲问了个Python函数中关于形参和实参一个很基础的问题,虽然很基础,但是对于很多小白来说不一定简单,反而会被搞得稀里糊涂.人生苦短,我用Python. 为了解答大家 ...

随机推荐

  1. Flume-NG一些注意事项(转)

    原文链接:记Flume-NG一些注意事项 这里只考虑flume本身的一些东西,对于JVM.HDFS.HBase等得暂不涉及.... 一.关于Source: 1.spool-source:适合静态文件, ...

  2. Nginx zabbix 的监控

    Nginx zabbix 的监控 Nginx 配置 Nginx 必须包含:http_stub_status_module 模块 ./nginx -V |grep http_stub_status_mo ...

  3. 8个超级震憾的Jquery图片特效欣赏,考验你的浏览器!

    这次主要是来分享几个个人觉得十分震憾的图片特效,有jQuery的,有CSS3的,有很萌的乌鸦动画,也有简单朴实的图片播放动画,当然有些你可能已经看到过了,不过也没关系,你能路过就算是对我的支持了. j ...

  4. GDB调试工具总结

    程序调试的基本思想是“分析现象->假设错误原因->产生新的现象去验证假设”这样一个循环过程,根据现象如何假设错误原因,以及如何设计新的现象去验证假设,需要非常严密的分析和思考.程序中除了一 ...

  5. Angular6

    Structural Directives https://angular.io/guide/structural-directives#template-input-variable There a ...

  6. MySQL监控主要指标及采集方法

    MySQL监控属于DB监控的模块之一,包括采集.展示.监控告警.本文主要介绍MySQL监控的主要指标和采集方法. MySQL监控和Redis监控的逻辑类似,可参考文章<Redis监控主要指标及采 ...

  7. 读取Style符号库样式的方法

    以前进行符化的时候一般都是自定义Symbol,或者使用SymbologyControl进行选择,由于实际需要,我们来读取一下样式管理器中的样式.在ArcMap中打开如下:style下有很多样式类,每个 ...

  8. Parse 使用- iOS 后台数据[转]

    原文地址:http://blog.csdn.net/vipwangl/article/details/8846415 最近在学习Parse,但是Parse的中文教程比较少,看到这篇英文教程,把它翻译一 ...

  9. Python面向对象编程 - 一个记事本程序范例(二)

    给程序加上控制台菜单 menu.py import sys from notebook import Notebook, Note class Menu: '''Display a menu and ...

  10. fcntl的区域锁定

    文件中的某个部分被锁定了,但其他的程序可以访问这个文件的其他部分,称为文件段锁定或文件区域锁定.经常使用文件区域锁定是fcntl函数. #include <sys/types.h> #in ...