返回介绍

任意参数的实例

发布于 2024-01-29 22:24:16 字数 3857 浏览 0 评论 0 收藏 0

最后两种匹配扩展,*和**,是让函数支持接受任意数目的参数的。它们都可以出现在函数定义或是函数调用中,并且它们在两种场合下有着相关的目的。

收集参数

第一种用法:在函数定义中,在元组中收集不匹配的位置参数。

当这个函数调用时,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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文