本部分内容基于《Python编程 从入门到实践》
函数是带名字的代码块,用于完成具体的任务。那么为什么我们需要编写函数?编写函数能够帮助我们完成大量重复的工作而无需每次编写相同的代码。此外,项目中函数的引入也能够让我们的代码具有更高的可读性、可修复性。
Python函数定义基本格式
下面以编程中最常见的Hello World!为例展示Python函数定义的基本格式:
def greet_world(): #(1)
"""print Hello World!""" #(2)
print ("Hello World!") #(3)
greet_world()
上面就是Python函数定义的基本格式,具体来看:
(1) 处通过 def 关键字告诉Python你要定义一个函数,同时定义了这个函数的名字为 greet_world,圆括号还能让我们放置一些函数完成任务所需要的参数,这个部分是 缺一不可 的。
(2) 处的文本称为 文档字符串 ,主要是描述本函数的作用,其格式为 三引号括起。
(3) 处就是函数中的代码。
所以综上所述,这个函数的功能就是打印出 Hello World!,而不需要任何参数传递给这个函数。
Python函数形参和实参
有时候我们需要向函数传递一些参数让函数能够做一些“个性化”的工作。例如,我们需要针对不同的人打印出不同的欢迎标语,例如 Hello, Mike!。
这个时候我们该怎么办呢?首先看如何编写函数:
def greet_user(username):
"""welcome a person"""
print(f"Hello, {username}!")
greet_user("Mike")
使用这个函数我们就能每次给它一个名字,然后它打印出我们想要的欢迎信息了。参数的功能正是如此。那么什么是 形参,什么是 实参 呢?
总结起来一句话,函数定义过程中的参数是形参,函数使用过程中的参数是实参。像上面的例子,函数定义中的 username 就是形参,函数使用中的 Mike 就是实参。
如何向Python函数传递实参
向Python函数传递实参的方法有两种:
一种是基于参数位置的使用 位置实参;
一种是基于形参的使用 关键字实参。
下面以一个实际例子阐述这两种不同的传递实参的方法:我们想编写一个函数,用于颁奖典礼的人员介绍,最终效果是打印出哪位同学来自哪个学校。首先还是构建函数:
def intro_person(name, university):
"""introduce a person"""
print(f"Let's welcome {name}!")
print(f"He is from {university}.")
-
位置实参
如果我们想要使用位置实参,就需要我们在向函数传递实参的时候对应上位置,也就是说我们的第一个实参必须是人名,第二个实参必须是学校名:
intro_person("Bio_Infor", "Nanjing University")
最终输出结果如下:
>>> Let's welcome Bio_Infor!
>>> He is from Nanjing University.
但是我们如果将实参的位置传反了:
intro_person("Nanjing University", "Bio_Infor")
出来的结果就不是我们想要的了:
>>> Let's welcome Nanjing University!
>>> He is from Bio_Infor.
-
关键字实参
位置实参一个知名的缺点就在于我们必须要每次记住函数的形参顺序,但是参数一多这就显得有点困难,这个时候我们就可以使用关键字实参。
intro_person(name = "Bio_Infor", university = "Nanjing University")
intro_person(university = "Nanjing University", name = "Bio_Infor")
由于我们使用了关键字实参,对应了实参和形参,所以这个时候上面两个不同的实参顺序最后函数运行出来的结果并没有不同~。
Python函数形参默认值
很多时候我们看到的函数并不需要我们提供所有的实参,它们会自动填充一些我们没有提供的实参,这就是默认值,在调用函数中给形参提供了实参之后,Python将使用指定的参数值,否则就会使用相残的默认值。使用默认值可以简化函数的使用。
例如上面的例子,我们不一定会收集到每个人具体的专业信息,没有时我们只能以philosophy (理学)来代替。
def intro_person(name, university, major = "philosophy"):
"""introduce a person"""
print(f"Let's welcome {name}, whose major is {major}")
print(f"He is from {university}.")
来给几个实参试试吧~
intro_person(university = "Nanjing University", name = "Bio_Infor")
这里没有给 major 参数,就使用了默认值,结果为:
>>> Let's welcome Bio_Infor, whose major is philosophy
>>> He is from Nanjing University.
当我们给了 major 对应的实参:
intro_person(university = "Nanjing University", name = "Bio_Infor", major = "Life Sciences")
结果就变了:
>>> Let's welcome Bio_Infor, whose major is Life Sciences
>>> He is from Nanjing University.
需要注意的是,使用默认值的形参必须放在函数定义的形参中最后的位置,否则将会报错。
Python函数实参变得可选
有的时候我们我们不一定有函数所需要的实参,这个时候该怎么办?还是以上面的专业信息为例:
def intro_person(name, university, major = ""):
"""introduce a person"""
if major:
print(f"Let's welcome {name}, whose major is {major}.")
print(f"He is from {university}.")
else:
print(f"Let's welcome {name}!")
print(f"He is from {university}.")
在Python中,非空的字符串会被解读为 True,所以如果我们给函数提供了 major 信息,if major 将为 True。
所以这个函数的运行结果是这样的:
intro_person(university = "Nanjing University", name = "Bio_Infor")
intro_person(university = "Nanjing University", name = "Bio_Infor", major = "Life Sciences")
>>> Let's welcome Bio_Infor!
>>> He is from Nanjing University.
>>> Let's welcome Bio_Infor, whose major is Life Sciences.
>>> He is from Nanjing University.
Python函数传递任意数量的实参
有的时候我们无法提前预知我们到底有多少实参,比如说我们需要对每位嘉宾最后一次性在大屏上打印欢迎信息,这个时候……我们可能无法提前知道会来哪些人,会来多少人。这就是我们如何向 Python函数传递任意数量的实参 的问题。先看函数:
def greet_persons(*args):
"""welcome persons"""
for arg in args:
print(f"Welcome, {arg}!")
具体来看:函数形参中的 * 能够让Python创建一个名为 args 的空元组,并将所有收到的值都封装到这个元组当中。我们可以把这个元组打印出来,看看是不是这样:
def greet_persons(*args):
"""welcome persons"""
print(args)
# for arg in args:
# print(f"Welcome, {arg}!")
greet_persons("Mike")
greet_persons("Mike", "Jason", "John")
我们可以看到,即使我们只传递了一个参数,也会构建出一个元组:
>>> ('Mike',)
>>> ('Mike', 'Jason', 'John')
然后我们通过遍历并打印这个元组中的元素就能够实现我们的目的:
def greet_persons(*args):
"""welcome persons"""
for arg in args:
print(f"Welcome, {arg}!")
greet_persons("Mike")
greet_persons("Mike", "Jason", "John")
结果:
>>> Welcome, Mike!
>>> Welcome, Mike!
>>> Welcome, Jason!
>>> Welcome, John!