Python程序设计
上QQ阅读APP看书,第一时间看更新

4.1.3 参数的传递

4.1.3 参数的传递

在Python函数中,实参向形参的传递方式有4种:按位置传递参数、按默认值传递参数、按关键字传递参数和按可变参数传递参数。

1.按位置传递参数

按位置传递参数是指,调用函数语句中实际参数的数量和位置,必须与函数定义中的形式参数的数量和位置一一对应,即第一个实参传递给第一个形参,第二个实参传递给第二个形参,以此类推。如果实参是一个表达式,则先计算表达式的值,再把计算后的结果传递给形参。

如果实参指向的对象是不可变的,如数值、字符串或元组对象等,即使在函数中改变了形参的值,实参指向的对象也不会发生任何改变。

例如,例4-8就是按位置传递参数,一个参数是不可变对象,一个参数是可变对象。

2.按默认值传递参数

在调用函数时,如果不指定某个参数,解释器会抛出异常。为了解决这个问题,Python允许为参数设置默认值,即在定义函数时,给形式参数指定一个默认值。这样,在调用函数时,可以选择性地省略该参数。如果没有给定义有默认值的形参传递参数,则该参数将使用定义函数时设置的默认值。Python中的函数可以给一个或多个形参(包括全部形参)指定默认值。定义带有默认值参数的函数,其语法格式如下:

说明:

1)有默认值的形参必须放在所有没有默认值形参的最后,否则会产生语法错误。

2)调用函数时,除了有默认值的形参外,其他形参必须有对应的实参传递值。

3)当函数有多个形参时,把变化大的形参放前面,变化小的形参放后面,这样变化小的参数就可以更方便地使用默认参数。

例4-9】 下面函数的功能是显示传入参数的值。

运行结果如下:

从运行结果看,第4行出现错误,原因是调用函数时传入的“女”字符串将传给age参数,而不是gender参数。所以,在省略默认参数时,要从后面向前省略。

3.按关键字传递参数

关键字参数是指使用形参的名字,以“形参名=值”的形式来输入参数值,这种形参和实参之间传值的方式称为关键字传值。由于在调用函数中通过形参名明确地指出对应关系,因此通过此方式指定函数实参时,不再需要与形参的位置完全一致。

按关键字传递参数,可以避免要牢记参数位置的麻烦,令函数的调用和参数传递更加灵活方便。因此函数的参数名应该具有更好的语义,这样程序员就可以明白传入函数的每个参数的含义。

例如,仍然调用例4-9定义的函数。

需要说明的是,如果希望在调用函数时混合使用关键字参数和位置参数,则关键字参数必须位于位置参数之后。换句话说,在关键字参数之后的只能是关键字参数。例如,如下代码是错误的。

注意,默认参数必须指向不变对象,否则在连续多次调用时,上次调用后的计算结果会保留,进而影响下次调用。

4.按可变参数传递参数

可变参数又称不定长参数,即传入函数中的实参可以是任意多个。

一般情况下,在定义函数时,函数形参的个数是可以确定的。但是,也有在定义函数的时候不能确定函数形参个数的情况。

在Python中,在形参前加一个星号(*)或两个星号(**)来指定函数可以接收任意数量的实参。定义可变参数函数的格式如下:

说明:

1)不带*的参数是普通形参。调用时,实参可选择按位置传递、按默认值传递或按关健字传递的方式使用。

2)形参tupleArg前面的*表示这是一个元组参数,默认值为()。

3)形参dictArg前面的**表示这是一个字典参数(键值对参数),默认值为{}。

4)可以把tupleArg和dictArg看成两个默认参数。

5)对于多余的非关键字参数,调用函数时放在元组参数tupleArg中。

6)对于多余的关键字参数,调用函数时放在字典参数dictArg中。

7)如果实参中的元组对象前面不带*,或者字典对象前面不带**,则作为普通的对象传递参数。

例4-10】 如下函数定义了一个个数可变的形参,可变参数为元组。

运行结果如下:

从上面的运行结果可以看出,当调用test()函数时,books参数可以传入多个字符串作为参数值。从test()的函数体代码来看,参数收集的本质就是将传给books参数的多个值收集成一个元组。

8)在实参列表中,如果使用*元组参数或者**字典参数,这两种参数应该放在参数列表最后,并且*元组参数位于**字典参数之前。

例4-11】 如下函数定义了两个个数可变的形参,一个可变参数为元组参数,另一个为字典参数。

程序在第1次调用test()函数时,前面的1、2、3传给普通参数a、b、c;接下来的两个字符串会由books参数收集成元组;最后的两个关键字参数会被收集成字典。运行程序,显示输出结果如图4-4中的前3行所示。

图4-4 例4-11运行结果

需要注意,对于以上方式定义的test()函数,参数c的默认值几乎不能发挥作用。第2次调用test()函数时,前面的1、2、"Python教程"将会传递给普通参数a、b、c;下一个字符串会由books参数收集成元组;最后的两个参数会被收集成字典。运行结果如图4-4中的中部3行所示。

如果希望让c参数的默认值发挥作用,则需要只传入两个位置参数。例如,第3次调用test()函数的实参列表,在调用test()函数时,前面的1、2将传给普通参数a、b,此时c参数将使用默认的参数值3,books参数将是一个空元组;接下来的两个关键字参数将会被收集成字典。运行结果如图4-4中的下部3行所示。

由于可能出现这种不可预知的结果,在编写程序时要注意避免出现这种情况。对于本例,可以不给c参数赋默认值。