文章目录

  • 问题剖析
  • 元组的使用

一个 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函数之可变默认参数相关推荐

  1. [转载] 详细介绍Python函数中的默认参数

    参考链接: Python函数中的默认参数 详细介绍Python函数中的默认参数 import datetime as dt def log_time(message, time=None): if t ...

  2. 站长在线Python精讲:在Python函数中的默认参数详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python函数中的默认参数详解>.本文的主要内容有:默认参数的概念和默认参数的示例.默认参数不能设置可变对象. 目录 1 ...

  3. python函数可变长参数_day14 Python函数之可变长参数

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

  4. 站长在线Python教程精讲:在Python函数中的关键字参数详解

    欢迎你来到站长在线的站长学堂学习Python知识,本文学习的是<在Python函数中的关键字参数详解>.本文的主要内容有:关键字参数的含义和关键字参数的应用举例. 目录 1.关键字参数的含 ...

  5. python默认参数 可变对象_当心Python函数可变默认参数(list,set,dict…)的陷阱

    绝大多数情况下,Python是一个干净具有一致性的语言.然而,有些少数情况会让初学者感到困惑.其中有些情况是有意识的但会成为潜在的莫名其妙,而有些可以说是语言赘肉.下面我们看看使用可变默认参数(Mut ...

  6. Python 函数的可变参数(*paramter与**paramter)的使用

    Python 函数的可变参数主要有 *paramter与**paramter 可变参数主要有 *paramter的作用 接受任意多个实际参数并放到一个元组中 def people(*people):f ...

  7. python默认参数 可变对象_最小经验原则(POLA)与可变默认参数

    题目 任何长时间学习Python的人都会遇到下面的问题. def foo(a=[]): a.append(5) return a Python初学者期望这个函数总是会返回一个只包含一个元素的列表:[5 ...

  8. “最少惊讶”和可变默认参数

    长时间修改Python的任何人都被以下问题咬伤(或弄成碎片): def foo(a=[]):a.append(5)return a Python新手希望此函数始终返回仅包含一个元素的列表: [5] . ...

  9. Python函数 — 位置参数和关键字参数

    1.参数分类 Python函数的参数可以分为默认参数,位置参数,关键字参数,可变参数.函数可以没有参数,也可以有多个参数. 形参:定义函数时的参数,如定义函数def func(a,b)的参数a,b是形 ...

最新文章

  1. 几何画板中隐藏坐标轴的步骤
  2. laravel 在三级分类下拉选框中默认值
  3. 职中计算机应用教学方法,职中《计算机应用基础》教学心得体会
  4. VTK:选择像素用法实战
  5. Bossie Awards 2015: The best open source applicati
  6. OFDM子载波频率 知乎_通过基于SDR的信号处理实现的低复杂度便携式无源无人机监控...
  7. python经济与管理学院学生社团管理系统设计与实现_实验10-大学生社团管理系统的设计和实现...
  8. 使用Freetype发现的问题记录
  9. 【情感识别】基于matlab GUI改进的KNN算法语音情感分类识别【含Matlab源码 354期】
  10. 图书馆图书借阅登记微信小程序管理软件系统开发制作
  11. 大地经纬度坐标系与Web墨卡托坐标系的转换
  12. 转载一篇让你全面了解什么是.NET。
  13. ai怎么做盒子效果图_AI教程:打造一个逼真的包装盒
  14. 第三方支付如何帮助在线教育打通支付
  15. 天津大学计算机专硕_天津大学计算机学院学硕和专硕哪个好?
  16. 【转载】SQL Server dateTime类型 模糊查询
  17. UE4学习笔记——粒子发射器
  18. Latex 中文简历 过程(更新Miktex和 修改utf字体)
  19. android oboe 混音_Android之AppBarLayout实现悬停吸附伸缩效果
  20. pwn - 格式化字符串攻击

热门文章

  1. 医用气体歧管的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  2. Android锁屏实践
  3. BGP建立邻居基础实验报告
  4. 美国人过去20年患阿尔茨海默症死亡率大幅上升,南部农村地区明显偏高
  5. 怎样查询自己的苹果手机各个软件的大小,占用多少内存?
  6. 【办公自动化】全网最全python中openpyxl库用法
  7. 对网站优化中木桶原理的几点思考
  8. 酷狗音乐盒缓存文件夹KuGouCache的设置方法
  9. java表示新年快乐,关于新年快乐祝贺语
  10. 鸿蒙圣地系统,鸿蒙圣地手游-鸿蒙圣地手游官网预约v1.0.0 - 逗游网