关于函数的学习(二) — 传递参数

传递实参

鉴于函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。向函数传递实参的方式很多,可使用位置实参,这要求实参的顺序与形参的顺序相同;也可使用关键字实参,其中每个实参都由变量名和值组成;还可使用列表和字典。

1.位置实参

你调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。

最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参。

例如:

1
2
3
4
5
handlebars复制代码def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet('hamster', 'harry')

这个函数的定义表明,它需要一种动物类型和一个名字。

调用describe_pet()时,需要按顺序提供一种动物类型和一个名字。

输出结果:

1
2
handlebars复制代码I have a hamster.
My hamster's name is Harry.

1.1调用函数多次

你可以根据需要调用函数任意次。

例如:

1
2
3
4
5
6
handlebars复制代码def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet('hamster', 'harry')
describe_pet('dog', 'willie')

打印结果为:

1
2
3
4
handlebars复制代码I have a hamster.
My hamster's name is Harry.
I have a dog.
My dog's name is Willie.

调用函数多次是一种效率极高的工作方式。我们只需在函数中编写描述的代码一次,然后每当需要时,都可调用这个函数,并向它提供新宠物的信息。

在函数中,可根据需要使用任意数量的位置实参,Python将按顺序将函数调用中的实参关联到函数定义中相应的形参。

1.2位置实参的顺序很重要

使用位置实参来调用函数时,如果实参的顺序不正确,结果可能出乎意料:

1
2
3
4
5
handlebars复制代码def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet('harry', 'hamster')

打印结果:

1
2
handlebars复制代码I have a harry.
My harry's name is Hamster.

顺序不正确,结果不一致。所以要确认函数调用中实参的顺序与函数定义中形参的顺序一致。   

2.关键字实参

关键字实参是传递给函数的名称—值对。

你直接在实参中将名称和值关联起来了,因此向函数传递实参时不会混淆。

关键字实参让你无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。

接着上面的例子:

1
2
3
4
5
handlebars复制代码def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet(animal_type='hamster', pet_name='harry')

打印结果:

1
2
handlebars复制代码I have a hamster.
My hamster's name is Harry.

关键字实参的顺序无关紧要,使用关键字实参时,务必准确地指定函数定义中的形参名。   

3.默认值

编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值。

给形参指定默认值后,可在函数调用中省略相应的实参。

使用默认值可简化函数调用,还可清楚地指出函数的典型用法。

例如:

1
2
3
4
5
handlebars复制代码def describe_pet(pet_name, animal_type='dog'):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet(pet_name='willie')

这里修改了函数describe_pet()的定义,在其中给形参animal_type指定了默认值’dog’。

调用这个函数时,如果没有给animal_type指定值,Python将把这个形参设置为’dog’:

1
2
handlebars复制代码I have a dog.
My dog's name is Willie.

请注意,在这个函数的定义中,修改了形参的排列顺序。

由于给animal_type指定了默认值,无需通过实参来指定动物类型,因此在函数调用中只包含一个实参——名字。

现在,使用这个函数的最简单的方式是,在函数调用中只提供名字:

1
handlebars复制代码describe_pet('willie')

这个函数调用的输出与前一个示例相同。只提供了一个实参——‘willie’,这个实参将关联到函数定义中的第一个形参——pet_name。由于没有给animal_type提供实参,因此Python使用其默认值’dog’。

如果要描述的动物不是小狗,可使用类似于下面的函数调用:

1
handlebars复制代码describe_pet(pet_name='harry', animal_type='hamster')

由于显式地给animal_type提供了实参,因此Python将忽略这个形参的默认值。

注意:使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的形参。

这让Python依然能够正确地解读位置实参。   

4.等效的函数调用

鉴于可混合使用位置实参、关键字实参和默认值,通常有多种等效的函数调用方式:

1
handlebars复制代码def describe_pet(pet_name, animal_type='dog'):

基于这种定义,在任何情况下都必须给pet_name提供实参;

指定该实参时可以使用位置方式,也可以使用关键字方式。

如果要描述的动物不是小狗,还必须在函数调用中给animal_type提供实参。

下面对这个函数的所有调用都可行:

1
2
3
4
5
6
7
handlebars复制代码# 一条名为Willie的小狗
describe_pet('willie')
describe_pet(pet_name='willie')
# 一只名为Harry的仓鼠
describe_pet('harry', 'hamster')
describe_pet(pet_name='harry', animal_type='hamster')
describe_pet(animal_type='hamster', pet_name='harry')

这些函数调用的输出与前面的示例相同。

注意:使用哪种调用方式无关紧要,只要函数调用能生成你希望的输出就行。使用对你来说最容易理解的调用方式即可。   

5.避免实参错误

等你开始使用函数后,你提供的实参多于或少于函数完成其工作所需的信息时,将出现实参不匹配错误。

例如,如果调用函数describe_pet()时没有指定任何实参,结果将如何呢?

1
2
3
4
5
6
7
8
9
10
11
handlebars复制代码def describe_pet(animal_type, pet_name):
"""显示宠物的信息"""
print("\nI have a "+animal_type+".")
print("My "+animal_type+"'s name is "+pet_name.title()+".")
describe_pet()
Python发现该函数调用缺少必要的信息,而traceback指出了这一点:
Traceback (most recent call last):
File "pets.py", line 6, in <module>
describe_pet()
TypeError: describe_pet() missing 2 required positional arguments: 'animal_
type' and 'pet_name'

traceback指出了问题出在什么地方,让我们能够回过头去找出函数调用中的错误。

还会指出了导致问题的函数调用。

traceback指出该函数调用少两个实参,并指出了相应形参的名称。

如果这个函数存储在一个独立的文件中,我们也许无需打开这个文件并查看函数的代码,就能重新正确地编写函数调用。

Python读取函数的代码,并指出我们需要为哪些形参提供实参,这提供了极大的帮助。这也是应该给变量和函数指定描述性名称的另一个原因;如果你这样做了,那么无论对于你,还是可能使用你编写的代码的其他任何人来说,Python提供的错误消息都将更有帮助。

如果提供的实参太多,将出现类似的traceback,帮助你确保函数调用和函数定义匹配。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%