函数
函数(Functions)是指可重复使用的程序片段。
白话的说,函数可类比为乐高积木,通过组合积木你可以搭建各种玩具,同样的,通过调用各种函数,你可以实现更复杂的代码功能。
Python官方已经为你实现了各种各样的函数,你只需调用(Calling)函数,而无需自己再次编写相关的功能。例如,计算一个字符串有多少个字符:
len('Python')
自定义函数
没有枪没有炮,你得自己造。
编程大部分的工作就是写函数,通过编写不同的函数,最终组合成一个软件系统。
例,计算2数之和:
def sum(a,b):
return a+b
# 调用函数
print(sum(5,6))
自定义函数需按以下模板编写:
def 函数名(参数1,参数2....参数n):
函数体
return 语句
def
表明这是一个函数 ,依次写出 函数名、括号、 括号中的参数 和冒号 :
,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。
函数参数
函数可以获取参数,这个参数的值由你所提供,借此,函数便可以利用这些值来做一些事情。这些参数与变量类似,这些变量的值在我们调用函数时已被定义,且在函数运行时均已赋值完成。
函数中的参数通过将其放置在用以定义函数的一对圆括号中指定,并通过逗号予以分隔。当我们调用函数时,我们以同样的形式提供需要的值。要注意在此使用的术语——在定义函数时给定的名称称作_“形参”(Parameters),在调用函数时你所提供给函数的值称作“实参”(Arguments)_。
案例(保存为 function_param.py
):
def print_max(a, b):
if a > b:
print(a, 'is maximum')
elif a == b:
print(a, 'is equal to', b)
else:
print(b, 'is maximum')
# 直接传递字面值
print_max(3, 4)
x = 5
y = 7
# 以参数的形式传递变量
print_max(x, y)
输出:
$ python function_param.py
4 is maximum
7 is maximum
它是如何工作的
在这里,我们将函数命名为 print_max
并使用两个参数分别称作 a
和 b
。我们使用一个简单的 if...else
语句来找出更大的那个数,并将它打印出来。
第一次调用函数 print_max
时,我们以实参的形式直接向函数提供这一数字。在第二次调用时,我们将变量作为实参来调用函数。print_max(x, y)
将使得实参 x
的值将被赋值给形参 a
,而实参 y
的值将被赋值给形参 b
。在两次调用中,print_max
都以相同的方式工作。
默认参数值
对于一些函数来说,你可能为希望使一些参数可选并使用默认的值,以避免用户不想为他们提供值的情况。默认参数值可以有效帮助解决这一情况。你可以通过在函数定义时附加一个赋值运算符(=
)来为参数指定默认参数值。
要注意到,默认参数值应该是常数。更确切地说,默认参数值应该是不可变的——这将在后面的章节中予以更详细的解释。就目前来说,只要记住就行了。
案例(保存为 function_default.py
):
def say(message, times=1):
print(message * times)
say('Hello')
say('World', 5)
输出:
$ python function_default.py
Hello
WorldWorldWorldWorldWorld
它是如何工作的
名为 say
的函数用以按照给定的次数打印一串字符串。如果我们没有提供一个数值,则将按照默认设置,只打印一次字符串。我们通过为参数 times
指定默认参数值 1
来实现这一点。
在第一次使用 say
时,我们只提供字符串因而函数只会将这个字符串打印一次。在第二次使用 say
时,我们既提供了字符串,同时也提供了一个参数 5
,声明我们希望说(Say)这个字符串五次。
注意
只有那些位于参数列表末尾的参数才能被赋予默认参数值,意即在函数的参数列表中拥有默认参数值的参数不能位于没有默认参数值的参数之前。
这是因为值是按参数所处的位置依次分配的。举例来说,
def func(a, b=5)
是有效的,但def func(a=5, b)
是无效的。
关键字参数
如果你有一些具有许多参数的函数,而你又希望只对其中的一些进行指定,那么你可以通过命名它们来给这些参数赋值——这就是关键字参数(Keyword Arguments)——我们使用命名(关键字)而非位置(一直以来我们所使用的方式)来指定函数中的参数。
这样做有两大优点——其一,我们不再需要考虑参数的顺序,函数的使用将更加容易。其二,我们可以只对那些我们希望赋予的参数以赋值,只要其它的参数都具有默认参数值。
案例(保存为 function_keyword.py
):
def func(a, b=5, c=10):
print('a is', a, 'and b is', b, 'and c is', c)
func(3, 7)
func(25, c=24)
func(c=50, a=100)
输出:
$ python function_keyword.py
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50
它是如何工作的
名为 func
的函数有一个没有默认参数值的参数,后跟两个各自带有默认参数值的参数。
在第一次调用函数时,func(3, 7)
,参数 a
获得了值 3
,参数 b
获得了值 7
,而 c
获得了默认参数值 10
。
在第二次调用函数时,func(25, c=24)
,由于其所处的位置,变量 a
首先获得了值 25。然后,由于命名——即关键字参数——指定,变量 c
获得了值 24
。变量 b
获得默认参数值 5
。
在第三次调用函数时,func(c=50, a=100)
,我们全部使用关键字参数来指定值。在这里要注意到,尽管 a
在 c
之前定义,但我们还是在变量 a
之前指定了变量 c
。
可变参数
有时你可能想定义的函数里面能够有_任意_数量的变量,也就是参数数量是可变的,这可以通过使用星号来实现(将下方案例保存为 function_varargs.py
):
def total(a=5, *numbers, **phonebook):
print('a', a)
#遍历元组中的所有项目
for single_item in numbers:
print('single_item', single_item)
#遍历字典中的所有项目
for first_part, second_part in phonebook.items():
print(first_part,second_part)
print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560))
输出:
$ python function_varargs.py
a 10
single_item 1
single_item 2
single_item 3
Inge 1560
John 2231
Jack 1123
None
它是如何工作的
当我们声明一个诸如 *param
的星号参数时,从此处开始直到结束的所有位置参数(Positional Arguments)都将被收集并汇集成一个称为“param”的元组(Tuple)。
类似地,当我们声明一个诸如 **param
的双星号参数时,从此处开始直至结束的所有关键字参数都将被收集并汇集成一个名为 param
的字典(Dictionary)。
我们将在后面的章节探索有关元组与字典的更多内容。
return
语句
return
语句用于从函数中返回,也就是中断函数。我们也可以选择在中断函数时从函数中返回一个值。
案例(保存为 function_return.py
):
def maximum(x, y):
if x > y:
return x
elif x == y:
return 'The numbers are equal'
else:
return y
print(maximum(2, 3))
输出:
$ python function_return.py
3
它是如何工作的
maximum
函数将会返回参数中的最大值,在本例中是提供给函数的数值。它使用一套简单的 if...else
语句来找到较大的那个值并将其返回。
要注意到如果 return
语句没有搭配任何一个值则代表着 返回 None
。None
在 Python 中一个特殊的类型,代表着虚无。举个例子, 它用于指示一个变量没有值,如果有值则它的值便是 None(虚无)
。
每一个函数都在其末尾隐含了一句 return None
,除非你写了你自己的 return
语句。你可以运行 print(some_function())
,其中 some_function
函数不使用 return
语句,就像这样:
def some_function():
pass
Python 中的 pass
语句用于指示一个没有内容的语句块。
提示:有一个名为
max
的内置函数已经实现了“找到最大数”这一功能,所以尽可能地使用这一内置函数。
DocStrings
Python 有一个甚是优美的功能称作文档字符串(Documentation Strings),在称呼它时通常会使用另一个短一些的名字docstrings。DocStrings 是一款你应当使用的重要工具,它能够帮助你更好地记录程序并让其更加易于理解。令人惊叹的是,当程序实际运行时,我们甚至可以通过一个函数来获取文档!
案例(保存为 function_docstring.py
):
def print_max(x, y):
'''打印两个数值中的最大数。
这两个数都应该是整数'''
# 如果可能,将其转换至整数类型
x = int(x)
y = int(y)
if x > y:
print(x, 'is maximum')
else:
print(y, 'is maximum')
print_max(3, 5)
print(print_max.__doc__)
输出:
$ python function_docstring.py
5 is maximum
打印两个数值中的最大数。
这两个数都应该是整数
它是如何工作的
函数的第一行逻辑行中的字符串是该函数的 文档字符串(DocString)。这里要注意文档字符串也适用于后面相关章节将提到的模块(Modules)与类(Class) 。
该文档字符串所约定的是一串多行字符串,其中第一行以某一大写字母开始,以句号结束。第二行为空行,后跟的第三行开始是任何详细的解释说明。[^5]在此强烈建议你在你所有重要功能的所有文档字符串中都遵循这一约定。
我们可以通过使用函数的 __doc__
(注意其中的双下划綫)属性(属于函数的名称)来获取函数 print_max
的文档字符串属性。只消记住 Python 将所有东西都视为一个对象,这其中自然包括函数。我们将在后面的类(Class)章节讨论有关对象的更多细节。
如果你曾使用过 Python 的 help()
函数,那么你应该已经了解了文档字符串的用途了。它所做的便是获取函数的 __doc__
属性并以一种整洁的方式将其呈现给你。你可以在上方的函数中尝试一下——只需在程序中包含 help(print_max)
就行了。要记住你可以通过按下 q
键来退出 help
。
自动化工具可以以这种方式检索你的程序中的文档。因此,我强烈推荐你为你编写的所有重要的函数配以文档字符串。你的 Python 发行版中附带的 pydoc
命令与 help()
使用文档字符串的方式类似。
总结
我们已经了解了许多方面的函数,但我们依旧还未覆盖到所有类型的函数。不过,我们已经覆盖到了大部分你每天日常使用都会使用到的 Python 函数。
接下来,我们将了解如何创建并使用 Python 模块。