1. 不要使用可变类型作为参数的默认值

摘自《流畅的Python》8.4.1

class HauntedBus:
"""备受幽灵乘客折磨的校车"""
def __init__(self, passengers=[]):
self.passengers = passengers def pick(self, name):
self.passengers.append(name) def drop(self, name):
self.passengers.remove(name)

运行测试用例

>>> bus1 = HauntedBus(['Alice', 'Bill'])
>>> bus1.passengers
['Alice', 'Bill']
>>> bus1.pick('Charlie')
>>> bus1.drop('Alice')
>>> bus1.passengers
['Bill', 'Charlie']
>>> bus2 = HauntedBus()
>>> bus2.pick('Carrie')
>>> bus2.passengers
['Carrie']
>>> bus3 = HauntedBus()
>>> bus3.passengers
['Carrie']
>>> bus3.pick('Dave')
>>> bus2.passengers
['Carrie', 'Dave']
>>> bus2.passengers is bus3.passengers
True
>>> bus1.passengers
['Bill', 'Charlie']

问题来了:登上 bus3 的 Dave 出现在 bus2 中。

原因在于,bus2.passengers 和 bus3.passengers 指代同一个列表。即没有指定初始乘客的 HauntedBus 实例会共享同一个乘客列表。

出现这个问题的根源是,默认值在定义函数时计算(通常在加载模块时),因此默认值变成了函数对象的属性。因此,如果默认值是可变对象,而且修改了它的值,那么后续的函数调用都会受到影响。

可以通过 __defaults__ 属性中的那些幽灵学生:

>>> dir(HauntedBus.__init__)  # doctest: +ELLIPSIS
['__annotations__', '__call__', ..., '__defaults__', ...]
>>> HauntedBus.__init__.__defaults__
(['Carrie', 'Dave'],)

可变默认值导致的这个问题说明了为什么通常使用 None 作为接收可变值的参数的默认

值。

最新文章

  1. Activemq mqtt 点对点聊天实现(转载)
  2. 关于MVC中View使用自定义方法
  3. R语言练习(一)
  4. Angularjs学习---angularjs环境搭建,ubuntu 12.04下安装nodejs、npm和karma
  5. WPF 模板
  6. MVC 过滤器
  7. Python-Day7 面向对象进阶/异常处理/Socket
  8. SaltStack Syndic配置
  9. poj 1068 Parencodings(栈)
  10. 性能测试工具 wrk 使用教程
  11. c/c++ 模板 类型推断
  12. 小技巧,把Markdown文本发布到微信公众号文章
  13. Maven打包后的文件存在中文乱码
  14. 背水一战 Windows 10 (89) - 文件系统: 读写文本数据, 读写二进制数据, 读写流数据
  15. linux 虚拟机挂载光驱
  16. idea下导入Tomcat源码
  17. VPC配置介绍
  18. iOS 坐标转换
  19. redis 3.2.3的源码安装
  20. CAS (14) —— CAS 更多用户信息

热门文章

  1. 【K8S】基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境(环境搭建篇)
  2. mysql运维入门6:MySQL读写分离
  3. 树状数组区间更新区间查询以及gcd的logn性质
  4. 【MySQL】详细说下MySQL删除数据的过程是什么样的?
  5. spring的各种注入
  6. COLA的扩展性使用和源码研究
  7. Azure Kubernetes 服务 (AKS)
  8. 剑指Offer之替换空格
  9. Java四种访问修饰符
  10. [Objective-C] 016_UI篇_UIView(上)