- 译者序
- 前言
- 第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 各部分练习题的解答
- 作者介绍
- 封面介绍
任意参数的实例
收集参数
第一种用法:在函数定义中,在元组中收集不匹配的位置参数。
当这个函数调用时,Python将所有位置相关的参数收集到一个新的元组中,并将这个元组赋值给变量args。因为它是一个一般的元组对象,能够索引或在一个for循环中进行步进。
**特性类似,但是它只对关键字参数有效。将这些关键字参数传递给一个新的字典,这个字典之后将能够通过一般的字典工具进行处理。在这种情况下,**允许将关键字参数转换为字典,你能够在之后使用键调用进行步进或字典迭代,如下段程序所示。
最后,函数头部能够混合一般参数、*参数以及**去实现更加灵活的调用方式。例如,在下面的代码中,1按照位置传递给a,2和3收集到pargs位置元组中,x和y放入kargs关键字词典中:
实际上,这种特性能够混合成更复杂的形式,以至于刚开始看上去有些糊涂,我们将会在本章稍后对这个概念进行复习。尽管如此,让我们先看一下在函数调用时而不是定义时使用*和**发生了什么吧。
解包参数
在最新的Python版本中,我们在调用函数时能够使用*语法。在这种情况下,它与函数定义的意思相反。它会解包参数的集合,而不是创建参数的集合。例如,我们能够通过一个元组给一个函数传递四个参数,并且让Python将它们解包成不同的参数。
相似地,在函数调用时,**会以键/值对的形式解包一个字典,使其成为独立的关键字参数。
另外,我们在调用中能够以非常灵活的方式混合普通的参数、基于位置的参数以及关键字参数。
在编写脚本时,当我们不能预测将要传入函数的参数的数量的时候,这种代码是很方便的。作为替代方法,能够在运行时创建一个参数的集合,并且可以统一使用这种方法进行函数的调用。另外,别混淆函数头部或函数调用时*/**的语法:在头部,它意味着收集任意数量的参数,而在调用时,它解包任意数量的参数。
注意:正如我们在第14章所见到过的,调用中的*pargs形式是一个迭代环境,因此技术上它接受任何可迭代对象,而不仅是像这里的示例所示的元组或其他序列。例如,一个文件对象在*之后工作,并且将其行解包为单个的参数(例如,func(*open('fname'))。
Python 3.0和Python 2.6都支持这种通用性,但是,它只对调用情况成立——调用中的*pargs允许任何可迭代对象,但是,一个def头部中的相同格式总是把额外的参数绑定到一个元组。这个头部行为在内涵上和语法上都与我们在第11章所介绍的Python 3.0扩展序列解包语法形式类似(例如x,*y=z),尽管该功能总是创建列表而不是元组。
应用函数通用性
前面小节的示例可能有些笨拙,但它们比我们想象的更常用。很多程序需要以通用的形式调用任意函数,提前并不知道函数的名称和参数。实际上,特殊的"varargs"调用的真正强大之处是,在编写一段脚本之前不需要知道一个函数调用需要多少参数。例如,可以使用if逻辑来从一系列函数和参数列表中选择,并且通用地调用其中任何一个:
更广泛地说,当你无法预计参数列表的任何时候,这种varargs调用语法很有用。例如,如果用户通过一个用户界面选择任意一个函数,你可能在编写自己的脚本的时候无法直接编写一个函数调用。要解决这个问题,直接用序列操作构建一个参数列表,并且用带星号的名称解包参数以调用它:
由于这里的参数列表时作为元组传入的,程序可以在运行时构建它。这种技术对于那些测试和计时其他函数的函数来说很方便。例如,在下面的代码中,我们通过传递任何发送进来的参数来支持具有任意参数的任意函数:
当这段代码运行的时候,tracer收集参数,然后以varargs调用语法来传递它:
我们将在本书随后看到这种用法的更大的例子,特别参见第20章的序列计时示例,以及我们将在第38章编写的装饰器工具。
废弃的apply内置函数(Python 2.6)
在Python 3.0之前,*args和**args varargs调用语法的效果可以通过一个名为apply的内置函数来实现。这一最初的技术在Python 3.0中已经废除了,因为它现在是多余的了(Python 3.0清除了众多的这类含糊不清但已经存在多年的工具)。它在Python 2.6中仍然可用,并且你可能会在旧的Python 2.X代码中遇到它。
简而言之,下面是前面的Python 3.0代码的对等形式:
例如,考虑如下的函数,它接受任意数量的可选关键字参数:
在Python 2.6中,我们可以用apply通用性地调用它,或使用Python 3.0中所必须的调用语法:
解包调用语法形式比apply函数新,通常也推荐使用它,并且是Python 3.0所必需的。除了它与def头部的*pargs和**kargs收集器对称,实际上它总体上需要较少的键盘录入,新的调用语法还允许我们传递额外的参数而不必手动扩展参数序列或字典:
也就是,这种调用语法形式更为通用。既然它在Python 3.0中是必须的,你现在应该忘掉关于apply的所有知识(除非,它出现在你必须使用或维护的Python 2.X代码中)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论