贡献者: addis; shizy0808
函数是组织好的,可重复使用的,用来实现相关功能的代码段。它能提高代码的重复利用率。Python 提供了许多内建函数,比如 print()
。我们也可以自己创建函数,这被叫做自定义函数。需要在程序中多次执行同一项任务时,你无需反复编写完成该任务的代码,而只需调用执行该任务的函数,让 Python 运行其中的代码。你将发现,通过使用函数,程序的编写、阅读、测试和修复都将更容易。
我们通过一个简单的例子开始介绍:
def func1():
# 定义一个函数,函数名为func1
print('hello python')
func1()
这个示例演示了最简单的函数结构。第一行的代码行使用关键字 def
来告诉 Python 我们要定义一个函数。然后向 Python 指出了函数名,还可能在括号内指出函数为完成其任务需要什么样的信息。在这里,函数名为 func1
,它不需要任何信息就能完成其工作,因此括号是空的(括号必不可少);最后,定义以冒号结尾,后面的所有缩进行构成了函数体。第二行处的文本是函数注释,以 #
开始,通常用来描述了函数是做什么的。
第三行 print('hello python')
是函数体内的唯一一行代码。
函数调用让 Python 执行函数的代码。要调用函数,可依次指定函数名以及用括号括起的必要信息,由于这个函数不需要任何信息,因
此调用它时只需输入 func1()
即可。
只需对上面函数稍作修改,就可以让函数 func1()
不仅向用户显示 hello python
,还将可以打印其他信息。在函数定义 def func1()
的括号内添加信息。通过在这里添加信息,就可让函数接受你给定的任何值。
def func2(str):
'''
改进第一个函数,使得它可以输出更多信息
输入:字符串
'''
print('hello'+str)
func2('C++')
func2('Tom')
输出
hello C++
hello Tom
上述代码在第一行函数定义处多了一个信息,函数功能变得更加丰富。同时我们注意到第二个用三个单引号开头,不再是 #
。三个单引号是用来进行多行注释的。另外注意到 Python 中字符串可以通过 +
来连接。
前面定义函数 func2
时,要求函数定义括号里面指定一个信息。调用这个函数并提供这种信息。实际上这个所谓的信息是一个形参,而在函数调用过程中,如 func2('C++')
,值 C++
是一个实参。实参是调用函数时传递给函数的信息。我们调用函数时,将要让函数使用的信息放在括号内。通俗的说,将函数定义中的变量称为形参,将函数调用中的变量称为实参。
函数定义中可能包含多个形参,因此函数调用中也可能包含多个实参。向函数传递实参的方式很多,可使用位置实参,这要求实参的顺序与形参的顺序相同; 也可使用关键字实参,其中每个实参都由变量名和值组成。
在调用函数时,Python 必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序,这种关联方式被称为位置实参。如 一个用来展示个人基本信息的函数定义如下:
def ShowInfo(name,age,ID):
'''
定义一个函数,来展示个人信息
name: 姓名
age: 年龄
ID: 学号
'''
print("my name is "+name+",my age is "+str(age)," and my ID is"+ID)
ShowInfo('XiaoMin', 16,'123456')
输出 my name is XiaoMin,my age is 16 and my ID is123456
。这个函数有三个参数,name
,age
,ID
,调用函数时候也需要指定三个参数,否则会报错,这三个参数的顺序与定义函数顺序一致,这就是位置参数。
关键字实参是传递给函数的名称-值对。在实参中将名称和值关联起来,因此向函数传递实参时不会混淆。关键字实参无需考虑函数调用中的实参顺序。
函数 ShowInfo()
还是原来那样,但调用这个函数时,我们向 Python 明确地指出了各个实参对应的形参。如:
ShowInfo(name='XiaoMin',ID='123456',age=16)
输出结果与之前一样,这时候不需要考虑参数的顺序。也可以按顺序填写位置参数,然后指定剩下参数的名字,如 ShowInfo('XiaoMin', ID='123456', age=16)
。
编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时,Python 将使用指定的实参值; 否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数 调用中省略相应的实参。使用默认值可简化函数调用,还可清楚地指出函数的典型用法。我们再次以展示个人信息为例:
def ShowInfo2(name,age=16,ID):
'''
定义一个函数,来展示个人信息
name: 姓名
age: 年龄
ID: 学号
'''
print("my name is "+name+",my age is "+str(age)," and my ID is"+ID)
调用函数
ShowInfo(name='XiaoMin',ID='123456')
ShowInfo(name='XiaoLi',ID='10086')
这里我们只给定了两个实参,而 age
使用了默认值,结果就会使用默认值。
函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值。函数返回的值被称为返回值。在 Python 函数中,可使用 return
语句将值返回到调用函数的代码行。返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。
下面我们定义一个函数,通过给定分数来返回对应的成绩登记。
def score(num):
'''
打分
:param num:
:return: 等级
'''
num = float(num)
if num>100 or num<0:
print('输入有误!')
if num>90:
return 'A'
elif num>80:
return 'B'
elif num>60:
return 'C'
else:
return 'D'
state =score(89)
print("state",state)
通函数 score
,返回成绩等级。
如果没有 return
,那么返回 None
。它的类型是 NoneType
。
若要返回多个值,用 return (val1, val2, ...)
,即返回一个 tuple
类型括号可省略。调用时用 (a, b) = fun(1, 2)
,第一个括号可省略。如果不需要某一个返回值,可以用 _
代替,例如 _, b = fun(1, 2)
。事实上这是 tuple
的语法而不是函数特有的,例如 (a, b) = (123, 234)
可以分别对 a, b
赋值,两个括号都分别可以省略。
向函数传递列表很有用,这种列表包含的可能是名字、数字或更复杂的对象。将列表传递给函数后,函数就能直接访问其内容。下面使用函数来提高处理列表的效率。假设有一个用户列表,我们要问候其中的每位用户。下面的示例将一个名字列表传递给一个名为 greet_users()
的函数,这个函数问候列表中的每个人。
def greet_users(names):
"""向列表中的每位用户都发出简单的问候"""
for name in names:
msg = "Hello, " + name.title() + "!"
print(msg)
usernames = ['xiaomin', 'toy', 'mar']
greet_users(usernames)
将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,即他可以改变原始列表。
有时候,我们预先不知道函数需要接受多少个实参,好在 Python 允许函数从调用语句中收集任意数量的实参。为了达到这个目的,在使用形参前加 *para
但不管调用语句提供了多少实参,这个形参都将它们包括进去。例如求和
def sum(*num):
# num 现在是一个 tuple
s=0
for i in num:
s = s+i
return s
print(sum(1,2,3))
print(sum(1,2,3,4))
两次调用函数分别传递了三个,四个参数。
f = lambda x,y: sqrt(x**2+y**2)
,这和用 def
定义是等价的。匿名函数体只能有一个表达式,默认 return 表达式的值。
一个函数可以调用在它前面或者后面定义的函数,也可以使用在它前面或后面定义的全局变量。但在函数外的代码只能调用它之前定义的函数和全局变量。