Python惯用法
2024-10-09 05:00:09
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 作为接收可变值的参数的默认
值。
最新文章
- Activemq mqtt 点对点聊天实现(转载)
- 关于MVC中View使用自定义方法
- R语言练习(一)
- Angularjs学习---angularjs环境搭建,ubuntu 12.04下安装nodejs、npm和karma
- WPF 模板
- MVC 过滤器
- Python-Day7 面向对象进阶/异常处理/Socket
- SaltStack Syndic配置
- poj 1068 Parencodings(栈)
- 性能测试工具 wrk 使用教程
- c/c++ 模板 类型推断
- 小技巧,把Markdown文本发布到微信公众号文章
- Maven打包后的文件存在中文乱码
- 背水一战 Windows 10 (89) - 文件系统: 读写文本数据, 读写二进制数据, 读写流数据
- linux 虚拟机挂载光驱
- idea下导入Tomcat源码
- VPC配置介绍
- iOS 坐标转换
- redis 3.2.3的源码安装
- CAS (14) —— CAS 更多用户信息
热门文章
- 【K8S】基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境(环境搭建篇)
- mysql运维入门6:MySQL读写分离
- 树状数组区间更新区间查询以及gcd的logn性质
- 【MySQL】详细说下MySQL删除数据的过程是什么样的?
- spring的各种注入
- COLA的扩展性使用和源码研究
- Azure Kubernetes 服务 (AKS)
- 剑指Offer之替换空格
- Java四种访问修饰符
- [Objective-C] 016_UI篇_UIView(上)