python函数之可变默认参数
文章目录
- 问题剖析
- 元组的使用
一个 Python Bug 干倒了估值 1.6 亿美元的公司
今天在CSDN首页看到这篇文章,不仅感概:
水能载舟,亦能覆舟
作为一家仰仗技术出身的公司,最终却因为技术的问题而断崖式地走向没落,实在令人唏嘘。技术既能让一家公司崛起,但使用不当、糊里糊涂或者想当然地去使用,可能一个小小的问题也足以摧毁一家公司。当然,在这里也不过多地聊这个故事,感兴趣的可以点文章链接详细看看。我就从技术的角度简单剖析下这里面出现的bug及其背后的原理。
问题剖析
这个问题涉及到python函数定义中的可变默认参数,那什么是可变默认参数呢?就拿文章中提到的函数举例:
def foo(l=[]):l.append(1)print(l)
在函数foo
中,参数l
是有默认值的,所以是一个默认参数,并且默认值是一个空列表[]
,而列表是属于可变对象,即不可散列的对象,因此参数l
就是一个可变默认参数。
在函数定义中,使用可变(不可散列unhashable)对象作为默认值的参数,就是可变默认参数
那么,在函数中使用可变默认参数会有什么问题呢?就像上面的函数foo
,很多人可能会想当然地认为,当不传递参数,多次调用函数foo()
的时候,输出的结果都是一样的,都是[1]
,但实际上偏偏想法,该函数的行为与我们预期的不符合:
可以看到,后面函数调用的输出确实不符合我们的预期,所以问题在哪里。其实只要搞清楚了python对函数的默认参数的管理机制和调用逻辑,这个问题就迎刃而解了。
首先,我们看看函数参数的默认值存在哪里,使用dir
看看函数对象的属性:
In [7]: dir(foo)
Out[7]:
['__annotations__','__call__','__class__','__closure__','__code__','__defaults__','__delattr__','__dict__','__dir__','__doc__','__eq__','__format__','__ge__','__get__','__getattribute__','__globals__','__gt__','__hash__','__init__','__init_subclass__','__kwdefaults__','__le__','__lt__','__module__','__name__','__ne__','__new__','__qualname__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__']
注意到,这里面有个__defaults__
,就是缺省、默认的意思,输出其内容:
In [8]: foo.__defaults__
Out[8]: ([1, 1, 1, 1, 1],)
但我们调用函数的时候,它的值也会随之改变:
In [9]: foo()
[1, 1, 1, 1, 1, 1]In [10]: foo.__defaults__
Out[10]: ([1, 1, 1, 1, 1, 1],)In [11]: foo()
[1, 1, 1, 1, 1, 1, 1]In [12]: foo.__defaults__
Out[12]: ([1, 1, 1, 1, 1, 1, 1],)In [13]: foo()
[1, 1, 1, 1, 1, 1, 1, 1]In [14]: foo.__defaults__
Out[14]: ([1, 1, 1, 1, 1, 1, 1, 1],)
我们重新定义foo
函数,在看看其__defaults__
属性的值:
In [15]: def foo(l=[]):...: l.append(1)...: print(l)...:In [16]: foo.__defaults__
Out[16]: ([],)
再做个实验,向__defaults__
中的列表对象添加一个数1024
,再调用函数,看看结果如何:
In [17]: foo.__defaults__[0].append(1024)In [18]: foo.__defaults__
Out[18]: ([1024],)In [19]: foo()
[1024, 1]
结果不出所料,在函数中向列表添加元素,其实就是向__defaults__
中的列表对象添加元素,也就是说函数中的l
变量和__defaults__
中的第一个元素引用的是同一个列表对象。所以从以上的分析可以看出函数对象的默认参数值确实是存放在其__defaults__
属性中。
到这里,我们应该大致了解了python函数默认参数的一些原理:
python函数之可变默认参数相关推荐
- [转载] 详细介绍Python函数中的默认参数
参考链接: Python函数中的默认参数 详细介绍Python函数中的默认参数 import datetime as dt def log_time(message, time=None): if t ...
- 站长在线Python精讲:在Python函数中的默认参数详解
欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python函数中的默认参数详解>.本文的主要内容有:默认参数的概念和默认参数的示例.默认参数不能设置可变对象. 目录 1 ...
- python函数可变长参数_day14 Python函数之可变长参数
函数参数 1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元.因此,形参只在函数内部有效.函数调用结束返回主调用函数后则不能再使用该形参变量 2.实参可以是常量.变量.表 ...
- 站长在线Python教程精讲:在Python函数中的关键字参数详解
欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python函数中的关键字参数详解>.本文的主要内容有:关键字参数的含义和关键字参数的应用举例. 目录 1.关键字参数的含 ...
- python默认参数 可变对象_当心Python函数可变默认参数(list,set,dict…)的陷阱
绝大多数情况下,Python是一个干净具有一致性的语言.然而,有些少数情况会让初学者感到困惑.其中有些情况是有意识的但会成为潜在的莫名其妙,而有些可以说是语言赘肉.下面我们看看使用可变默认参数(Mut ...
- Python 函数的可变参数(*paramter与**paramter)的使用
Python 函数的可变参数主要有 *paramter与**paramter 可变参数主要有 *paramter的作用 接受任意多个实际参数并放到一个元组中 def people(*people):f ...
- python默认参数 可变对象_最小经验原则(POLA)与可变默认参数
题目 任何长时间学习Python的人都会遇到下面的问题. def foo(a=[]): a.append(5) return a Python初学者期望这个函数总是会返回一个只包含一个元素的列表:[5 ...
- “最少惊讶”和可变默认参数
长时间修改Python的任何人都被以下问题咬伤(或弄成碎片): def foo(a=[]):a.append(5)return a Python新手希望此函数始终返回仅包含一个元素的列表: [5] . ...
- Python函数 — 位置参数和关键字参数
1.参数分类 Python函数的参数可以分为默认参数,位置参数,关键字参数,可变参数.函数可以没有参数,也可以有多个参数. 形参:定义函数时的参数,如定义函数def func(a,b)的参数a,b是形 ...
最新文章
- 几何画板中隐藏坐标轴的步骤
- laravel 在三级分类下拉选框中默认值
- 职中计算机应用教学方法,职中《计算机应用基础》教学心得体会
- VTK:选择像素用法实战
- Bossie Awards 2015: The best open source applicati
- OFDM子载波频率 知乎_通过基于SDR的信号处理实现的低复杂度便携式无源无人机监控...
- python经济与管理学院学生社团管理系统设计与实现_实验10-大学生社团管理系统的设计和实现...
- 使用Freetype发现的问题记录
- 【情感识别】基于matlab GUI改进的KNN算法语音情感分类识别【含Matlab源码 354期】
- 图书馆图书借阅登记微信小程序管理软件系统开发制作
- 大地经纬度坐标系与Web墨卡托坐标系的转换
- 转载一篇让你全面了解什么是.NET。
- ai怎么做盒子效果图_AI教程:打造一个逼真的包装盒
- 第三方支付如何帮助在线教育打通支付
- 天津大学计算机专硕_天津大学计算机学院学硕和专硕哪个好?
- 【转载】SQL Server dateTime类型 模糊查询
- UE4学习笔记——粒子发射器
- Latex 中文简历 过程(更新Miktex和 修改utf字体)
- android oboe 混音_Android之AppBarLayout实现悬停吸附伸缩效果
- pwn - 格式化字符串攻击
热门文章