Fluent Python: Mutable Types as Parameter Defaults: Bad Idea
在Fluent Python一书第八章有一个示例,未看书以先很难理解这个示例运行的结果,我们先看结果,然后再分析问题原因:
定义了如下Bus类:
class Bus:
def __init__(self, passengers=[]):
self.passengers = passengers def pick(self, name):
self.passengers.append(name) def drop(self, name):
self.passengers.remove(name)
创建两个Bus 类实例,bus1, bus2
>>> import Example8_12
>>> bus1 = Example8_12.Bus()
>>> bus2 = Example8_12.Bus()
假如bus1接到一个一名乘客Alice:
>>> bus1.pick('Alice')
此时我们看看bus2里的乘客:
>>> bus2.passengers
['Alice']
bus2本应该是空的,但是此时却有bus1 pick的乘客'Alice', 这是什么原因呢?
出现这个问题的根源是:默认值在定义函数时计算(通常是在import 模块时),并且默认值变成了函数对象的属性:
我们可以省察下类Bus __init__方法的属性
>>> dir(Example8_12.Bus.__init__)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
留意其中有个__defaults__属性,我们看看其中的内容:
>>> Example8_12.Bus.__init__.__defaults__
(['Alice'],)
我们可以看到'Alice'正在其中,这也是为什么bus2里会有乘客'Alice'的原因.
我们可以验证bus2.passengers是一个别名,它绑定到Bus1.__init__.__defaults__属性的第一个元素上了:
>>> Example8_12.Bus.__init__.__defaults__[0] is bus2.passengers
True
这个示例说明了为什么通常使用None作为接收可变值的参数的默认值。
这个类正确的书写应该如下:
class Bus:
def __init__(self, passengers=None):
if passengers is None:
self.passengers = []
else:
self.passengers = list(passengers) def pick(self, name):
self.passengers.append(name) def drop(self, name):
self.passengers.remove(name)
这里有一个原则,如果定义的函数接收可变参数,应该谨慎考虑调用方是否期望修改传入的参数。
Fluent Python: Mutable Types as Parameter Defaults: Bad Idea的更多相关文章
- 学习笔记之Fluent Python
Fluent Python by Luciano Ramalho https://learning.oreilly.com/library/view/fluent-python/97814919462 ...
- 「Fluent Python」今年最佳技术书籍
Fluent Python 读书手记 Python数据模型:特殊方法用来给整个语言模型特殊使用,一致性体现.如:__len__, __getitem__ AOP: zope.inteface 列表推导 ...
- Fluent Python: memoryview
关于Python的memoryview内置类,搜索国内网站相关博客后发现对其解释都很简单, 我觉得学习一个新的知识点一般都要弄清楚两点: 1, 什么时候使用?(也就是能解决什么问题) 2,如何使用? ...
- python的types模块
python的types模块 1.types是什么: types模块中包含python中各种常见的数据类型,如IntType(整型),FloatType(浮点型)等等. >>> im ...
- Python深入学习之《Fluent Python》 Part 1
Python深入学习之<Fluent Python> Part 1 从上个周末开始看这本<流畅的蟒蛇>,技术是慢慢积累的,Python也是慢慢才能写得优雅(pythonic)的 ...
- Fluent Python: Classmethod vs Staticmethod
Fluent Python一书9.4节比较了 Classmethod 和 Staticmethod 两个装饰器的区别: 给出的结论是一个非常有用(Classmethod), 一个不太有用(Static ...
- Fluent Python: @property
Fluent Python 9.6节讲到hashable Class, 为了使Vector2d类可散列,有以下条件: (1)实现__hash__方法 (2)实现__eq__方法 (3)让Vector2 ...
- 《Fluent Python》---一个关于memoryview例子的理解过程
近日,在阅读<Fluent Python>的第2.9.2节时,有一个关于内存视图的例子,当时看的一知半解,后来查了一些资料,现在总结一下,以备后续查询: 示例复述 添加了一些额外的代码,便 ...
- [Python] Pitfalls: About Default Parameter Values in Functions
Today an interesting bug (pitfall) is found when I was trying debug someone's code. There is a funct ...
随机推荐
- acm--1004
问题描述 再次比赛时间!看到气球在四周漂浮,多么兴奋.但要告诉你一个秘密,评委最喜欢的时间是猜测最流行的问题.比赛结束后,他们会统计每种颜色的气球并找出结果. 今年,他们决定离开这个可爱的工作给你. ...
- Linux 学习第五天
一.重定向.管道符.通配符 1.重定向.管道符使用 重定向: 命令文件 管道符: 命令A:命令B (管道符 | 别称 “任意门”) 二.常用命令 1.ls /etc | wc -l (查看目录 ...
- canvas常用属性方法由浅下沉
首先引入<canvas></canvas>标签就不必说了. 其次就是得到canvas的2d环境了( var ctx = canvasDom.getContext('2d') ) ...
- windows 10 安装node.js
第一步:下载软件 nodejs的中文官网http://nodejs.cn/download/ 选择 windows 系统 msi 安装版本. 下载完成之后,直接打开下一步安装就可以. 安装完成 打开 ...
- 企业网站被黑 dedecms漏洞修复办法
前段时间网站被黑了,从百度打开网站直接被劫持跳转到了彩票,du博网站上去,网站的首页index.html文件也被篡改成一些什么北京sai车,pk10,一些cai票的关键词内容,搞得网站根本无法正常浏览 ...
- Node.js的Formidable模块的使用,方便快捷
服务用的是express ,如果不是很老的express框架,都有自带formidable 如果没有就下载一个 npm i formidable var formidable = require( ...
- MySQL入门第一天——概述、数据表与约束操作
一.概述 1.安装 初学MySQL,我们下载msi的安装版:http://dev.mysql.com/downloads/file.php?id=457403 安装的过程文字简述可以参考之前随笔:ht ...
- 【调试】Linux下超强内存检测工具Valgrind
[调试]Linux下超强内存检测工具Valgrind 内容简介 Valgrind是什么? Valgrind的使用 Valgrind详细教程 1. Valgrind是什么? Valgrind是一套Lin ...
- HTML5 离线应用程序
离线Web应用:当客户端本地与Web应用程序的服务器没有建立连接时,也能正常在客户端本地使用该Web应用. Web应用程序的本地缓存与浏览器的网页缓存的区别 1. 本地缓存为整个Web应用程序服务,网 ...
- MongoDB-Ubuntu环境下安装
1.在官网下载安装包,下载后为 mongodb-linux-x86_64-ubuntu1604-3.4.6.tgz 解压:tar -zxvf mongodb-linux-x86_64-ubuntu16 ...