add by zhj: 文章写的很好,其实只要默认参数在函数中只读不写,那默认值就不会被修改,可变类型做默认参数就不会有问题

方法二中,当result is None时,修改result的指向,不再指向默认参数对象,而是赋值一个新的对象。如下,可以看到,result的id变化了

In [4]: def f(p=None, q=[]):
...: print id(p), id(q)
...: if p is None:
...: p = []
...: print id(p)
...: In [5]: f()
9568656 140309648126608
140309648094632 In [6]: f()
9568656 140309648126608
140309648074944

原文:https://blog.csdn.net/sinat_38068807/article/details/85677419

说明:默认参数值在函数被定义时已经计算出来,而不是在程序运行时。Python 程

序员经常犯的一个错误是把可变的数据类型(例如列表或者字典)当作默认参数值

(一)出现的问题

在下面的例子中,函数 buggy() 在每次调用时,添加参数 arg 到一个空的列表 result ,然
后打印输出一个单值列表。但是存在一个问题:只有在第一次调用时列表是空的,第二次
调用时就会存在之前调用的返回值

def buggy(arg, result=[]):
result.append(arg)
print(result) print('--------1--------')
buggy('a')
print('--------2--------')
buggy('b') # 期望得到 ['b']

执行结果:

--------1--------
['a']
--------2--------
['a', 'b']

(二)解释并测试

1.默认参数值在函数被定义时已经计算出来,而不是在程序运行时

2.只要函数调用时没有传递新的列表来覆盖默认参数列表,函数就会使用定义时的那个列表,并且操作依次叠加

3.上面两次调用中,都没有传递新的列表,程序会调用定义函数时保存的默认参数,并在上一次的基础上进行操作叠加,即:列表在append的时候会在 result原来的基础上append追加值,所以会产生以上结果.

我们通过打印列表的ID进行辨识来看看:

def buggy(arg, result=[]):
print(id(result))
result.append(arg)
print(result) print('--------1--------')
buggy('a')
print('--------2--------')
buggy('b') # expect ['b']

结果:

--------1--------
12205768
['a']
--------2--------
12205768
['a', 'b']

我们会发现ID值是相同的;

说明两次执行时使用的都是开始定义函数时的默认参数 ,进行了操作叠加

4.下面我们传递新的列表看看:

def buggy(arg, result=[]):
print(id(result))
result.append(arg)
print(result) print('--------1--------')
buggy('a')
print('--------2--------')
buggy('b', []) # 传递了新的列表

结果:

--------1--------
18497224
['a']
--------2--------
18504648
['b']

发现,列表id不同,并且得到了我们期望的值

(三)解决方法

方法1

# 如果写成下面的样子就会解决刚才的问题:

def works(arg):
result = []
result.append(arg)
print(result) works('a')
works('b')

结果:

['a']
['b']

方法2:

# 这样的修改也为了表明是第一次调用跳过一些操作:

def nonbuggy(arg, result=None):
if result is None:
result = []
result.append(arg)
print(result) nonbuggy('a')
nonbuggy('b')

结果:

['a']
['b']

python函数把可变数据类型当默认参数值的问题(转)的更多相关文章

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

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

  2. python基础之可变数据类型与不可变数据类型

    一.什么可变数据类型和不可变数据类型 可变数据类型:value值改变,id值不变:不可变数据类型:value值改变,id值也随之改变. 二.如何确定一种数据类型是可变的还是不可变的 根据可变数据类型与 ...

  3. python中不可变数据类型和可变数据类型

    在学习python过程中我们一定会遇到不可变数据类型和可变数据类型. 1.名词解释 以下所有的内容都是基于内存地址来说的. 不可变数据类型: 当该数据类型的对应变量的值发生了改变,那么它对应的内存地址 ...

  4. Python 函数(可变参数)

    在python函数中,可以定义可变参数,顾名思义,可变参数就是,传入的参数是可变的例如,给定一组数字a,b,c...  请计算a2 + b2 + c2 + …… 要定义出这个函数,我们必须确定输入的参 ...

  5. python 函数传递可变参数的用法

    可变参数 在Python函数中,还可以定义可变参数.顾名思义,可变参数就是传入的参数个数是可变的,可以是1个.2个到任意个,还可以是0个. 我们以数学题为例子,给定一组数字a,b,c……,请计算a2 ...

  6. python中的可变数据类型和不可变数据类型

    1.不可变数据类型:数值.字符串.元组 不允许变量的值发生变化,如果变量的值变化了,那么就是新建了一个对象:对于相同值的对象,在内存中只有一个对象. 2.可变数据类型:列表.字典 允许变量的值发生变化 ...

  7. day14 Python函数之可变长参数

    函数参数 1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元.因此,形参只在函数内部有效.函数调用结束返回主调用函数后则不能再使用该形参变量 2.实参可以是常量.变量.表 ...

  8. 【转】Python函数默认参数陷阱

    [转]Python函数默认参数陷阱 阅读目录 可变对象与不可变对象 函数默认参数陷阱 默认参数原理 避免 修饰器方法 扩展 参考 请看如下一段程序: def extend_list(v, li=[]) ...

  9. Python面试题目之Python函数默认参数陷阱

    请看如下一段程序: def extend_list(v, li=[]): li.append(v) return li list1 = extend_list(10) list2 = extend_l ...

随机推荐

  1. Mockito框架入门教程(二)

    接上一篇,继续学习其它的.... 8.找出冗余的互动(即未被验证到的) @Test(expected = NoInteractionsWanted.class) public void find_re ...

  2. PHP实现微信开发中提现功能(企业付款到用户零钱)

    一.实现该功能目的 这几天在小程序里要实现用户从系统中提现到零钱的功能,查了一下文档可以使用 企业付款到用户零钱 来实现: 官方文档:https://pay.weixin.qq.com/wiki/do ...

  3. 一次lr异常Error: C interpreter run time error: Action.c (17): Error -- memory violation : Exception ACCESS_VIOLATION received问题分析

    今天qq群里人问我一个问题 人家的原始问题如下: 问题是为啥通过lr_save_string取不到参数值 由于别的问题,我也需要调试,但是没有环境,只能模拟场景,如下 他想将token变量换成lr中的 ...

  4. 咸鱼入门到放弃4——Http协议

    一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的 ...

  5. 监听F5刷新,添加路由前缀

    为了解决ninx反向代理,添加路由,但最终react的route还是不认识,研究了半天做个记录: document.addEventListener("keydown",funct ...

  6. iOS12系统应用发送邮件中的附件

    iOS12系统应用发送邮件中的附件 iOS12系统应用发送邮件中的附件,如果发送邮件的内容很多,或者包含文档.图片等,可以以附件的形式进行发送.此时需要使用addAttachmentData(_:mi ...

  7. 识别拖动与点击操作之zepto的bug

    问题描述:给页面<a>标签绑定了tap事件,在移动设备上点击按钮貌似一切正常,可以响应.但是,把页面上下滑动几次之后,或者在滑动时手指滑动出移动屏幕之外,之后再点击按钮,就会发现第一次点击 ...

  8. eclipse导入新项目配置jdk、tomcat到浏览器正常访问

    好记性不如烂笔头,长时间不操作就会生疏,在此做个笔记 1.导入项目 2,进入选择项目,点finish完成,导入成功 3.配置tomcat和jdk 选择本地相对应jdk的jre 选择tomcat版本进行 ...

  9. 英语口语练习系列-C38-颜色-谈论日常活动

    词汇颜色 color red passion green peace energy blue calm purple mystery yellow royal 询问日常生活 When do you g ...

  10. Python matplotlib图片转化成矢量图并裁剪

    Python目前可以生成的图的格式是:eps, jpeg, jpg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff 在写论文时候我一般生成png ...