- 译者序
- 前言
- 第1章 问答环节
- 第2章 Python 如何运行程序
- 第3章 如何运行程序
- 第4章 介绍 Python 对象类型
- 第5章 数字
- 第6章 动态类型简介
- 第7章 字符串
- 第8章 列表与字典
- 第9章 元组、文件及其他
- 第10章 Python 语句简介
- 第11章 赋值、表达式和打印
- 第12章 if 测试和语法规则
- 第13章 while 和 for 循环
- 第14章 迭代器和解析,第一部分
- 第15章 文档
- 第16章 函数基础
- 第17章 作用域
- 第18章 参数
- 第19章 函数的高级话题
- 第20章 迭代和解析,第二部分
- 第21章 模块:宏伟蓝图
- 第22章 模块代码编写基础
- 第23章 模块包
- 第24章 高级模块话题
- 第25章 OOP:宏伟蓝图
- 第27章 更多实例
- 第28章 类代码编写细节
- 第29章 运算符重载
- 第30章 类的设计
- 第31章 类的高级主题
- 第32章 异常基础
- 第34章 异常对象
- 第35章 异常的设计
- 第36章 Unicode 和字节字符串
- 字符串基础知识
- Python 的字符串类型
- 文本和二进制文件
- Python 3.0 中的字符串应用
- 转换
- 编码 Unicode 字符串
- 编码非ASCII文本
- 编码和解码非ASCII文本
- 其他 Unicode 编码技术
- 转换编码
- 在 Python 2.6 中编码 Unicode 字符串
- 源文件字符集编码声明
- 使用 Python 3.0 Bytes 对象
- 序列操作
- 创建 bytes 对象的其他方式
- 混合字符串类型
- 使用 Python 3.0(和 Python 2.6)bytearray 对象
- 使用文本文件和二进制文件
- Python 3.0 中的文本和二进制模式
- 类型和内容错误匹配
- 使用 Unicode 文件
- 在 Python 3.0 中处理 BOM
- Python 2.6 中的 Unicode 文件
- Python 3.0 中其他字符串工具的变化
- Struct二进制数据模块
- pickle对象序列化模块
- XML解析工具
- 本章小结
- 本章习题
- 习题解答
- 第37章 管理属性
- 第38章 装饰器
- 第39章 元类
- 附录A 安装和配置
- 附录B 各部分练习题的解答
- 作者介绍
- 封面介绍
默认和可变对象
这也就是通常我们所想要的:因为默认参数是在def时被评估的,如果必要的话,它能够从整个作用域内保存值,但是因为默认参数在调用之间都保存了一个对象,必须对修改可变的默认参数十分小心。例如,下面的函数使用了一个空列表作为默认参数,并在函数每次调用时都对它进行了改变。
有些人把这种行为当作一种特性。因为可变类型的默认参数在函数调用之间保存了它们的状态,从某种意义上讲它们能够充当C语言中的静态本地函数变量的角色。在一定程度上,它们工作起来就像全局变量,但是它们的变量名对于函数来说是本地变量,而且不会与程序中的其他变量名发生冲突。
尽管这样,对于大多数人来说,这看起来就像是一个陷阱,特别第一次遇到这样的情况的时候。在Python中有更好的办法在调用之间保存状态(例如,使用类,这将在第6部分进行讨论)。
此外,可变类型默认参数记忆起来比较困难(理解起来也不容易)。它们的值取决于默认对象构建的时间。在上一个例子中,其中只有一个列表对象作为默认值,这个列表对象是在def语句执行时被创建的。不会每次函数调用时都得到一个新的列表,所以每次新的元素加入后,列表会变大,对于每次调用,它都没有重置为空列表。
如果这不是你想要的行为的话,在函数主体的开始对默认参数进行简单的拷贝,或者将默认参数值的表达式移至函数体内部。只要值是存在于在代码中,而这部分代码在函数每次运行时都会执行的话,你就会每次都得到一个新的对象。
顺便提一下,这个例子中的if语句可以被赋值语句x=x or[]来代替,这个赋值语句将会利用Python的or语句返回操作符对象中的一个的特性:如果没有参数传入的话,x将会默认为None,所以or将会返回右边的空列表。
尽管如此,这还不是完全相同的。如果是一个空列表被传入,or表达式将会导致函数扩展并返回一个新创建的列表,而不是像if版本那样扩展并返回传入的列表。(表达式变成[]or[],将会设置为右边空列表的值。参看第12章中的相关内容,如果你想不起来为什么的话)。真正的程序也许都需要这两种行为。
如今,以一种较少令人混淆的方式来实现可变默认值效果的另一种方式,是使用我们在第19章讨论过的函数属性:
该函数的名称对于函数自身来说是全局的,但是,它不需要声明,因为它在函数内部是不会直接修改的。这并不是总是以完全相同的方式使用,但是,当这样编写代码的时候,一个对象到函数的附加总是更加明确(并且肯定更容易理解)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论