3.1 懒人炒菜机
1.函数是什么
函数(Function)这个名字会让人想起中学数学,所以会带来轻微的痛苦。在数学上,函数代表了集合之间的对应关系。譬如说,所有的汽车是一个集合,所有的方向盘也是一个集合。汽车集合和方向盘集合之间存在着对应关系,可以表达为一个函数。
我们再举一个数学上的例子。下面的平方函数,将一个自然数对应为这个自然数的平方:
f(x)=x2, x是一个自然数
换句话说,函数 f(x) 定义了两组数字之间的对应关系:
x -> y
1 1
2 4
3 9
4 16
…
数学上的函数定义了静态的对应关系。从数据的角度来说,函数像是“大变活人”的魔法盒子,这个魔法盒子能把走进去的小猪变成小兔子(如图3-1所示)。对于刚才定义的函数 f(x) ,进去的是一个自然数,出来的是这个自然数的平方。借着函数,我们实现了数据转换。
图3-1 魔法盒子
函数的魔法转换并非凭空生成。对于编程中的函数,我们可以用一系列指令来说明函数是如何工作的。编程中的函数在实现数据转换的同时,还能借着指令,实现其他功能。所以,程序员还可以从程序封装的角度来理解函数。
对于程序员来说,函数是这样一种语法结构。它把一些指令封装在一起,形成一个组合拳。一旦定义好了函数,我们就可以通过对函数的调用,来启动这套组合拳。因此,函数是对封装理念的实践。输入数据被称为参数,参数能影响函数的行为。这就好比同样的组合拳可以有不同的力量级别。
这样,我们就有了三种看待函数的方式:集合的对应关系、数据的魔法盒子、语句的封装。编程教材一般会选择其一来说明函数是什么。这三种解释方式都正确,区别只是看待问题的角度。相互参照三种互通的解释方式,可以更充分地理解函数是什么。
2.定义函数
我们首先制作一个函数。制作函数的过程又称为定义函数(define function)。我们称这个函数为square_sum()。人如其名,这个函数的功能是计算两个数的平方和:
def square_sum(a,b):
a = a**2
b = b**2
c = a + b
return c
最先出现的是def这个关键字。这个关键字通知Python“这里要定义函数了”。关键字def后面跟着square_sum,即函数的名字。在函数名后面,还有一个括号,用来说明函数有哪些参数,即括号中的a和b。参数可以有多个,也可以完全没有。根据Python的语法规定,即使没有输入数据,函数后面的括号也要保留。
在定义函数时,我们用了a和b两个符号来指代输入数据。等到真正使用函数时,我们才会说明a和b具体是什么样的数字。所以,定义函数就像是练武术架式,真正调用函数时才借着真实的输入数据决定出手力度。参数在函数定义的内部起到了和变量类似的功能,可以用符号化的形式参与到任何一行指令中。由于函数定义中的参数是一个形式代表,并非真正数据,所以又称为形参(Parameter)。
在定义函数square_sum()时,我们用参数a和b完成了符号化的平方求和。而在函数的具体执行中,参数所代表的数据确实是作为一个变量存在的,我们将在后面详述这一点。
括号结束时,就来到了第一行的末尾。末尾有一个冒号,后面的四行都有缩进。联系在第2章中的学习,我们可以推测出这里的冒号和缩进表示了代码的隶属关系。因此,后面的四行有缩进的代码都是函数square_sum()的小弟。函数是对代码的封装。当函数被调用时,Python将执行从属于函数的语句,直到从属语句结束。对于square_sum()来说,它的前三行都是我们已经熟悉了的运算语句。最后一句是return。关键字return用于说明函数的返回值,即函数的输出数据。
作为函数的最后一句,函数执行到return时就会结束,不管它后面是否还有其他函数定义语句。如果把square_sum()改为下面的形式:
def square_sum(a,b):
a = a**2
b = b**2
c = a + b
return c
print("am I alive?")
则函数执行时,只会执行到return c。后面一句print()虽然也归属于函数,却不会被执行。所以,return还起到了中止函数和制定返回值的功能。在Python的语法中,return并不是必需的。如果没有return, 或者return后面没有返回值时,则函数将返回None。None是Python中的空数据,用来表示什么都没有。关键字return也返回多个值。多个值跟在return后面,以逗号分隔。从效果上看,其等价于返回一个有多个数据的元组。
return a,b,c # 相当于 return (a,b,c)
3.调用函数
上面我们看到怎样定义函数。定义函数就像打造了一把利器,但这件兵器必须使用起来,才能真正发挥作用。使用函数的过程叫作调用函数(Call Function)。在第1章中,我们已经见过如何调用print()函数:
print("Hello World!")
我们直接使用了函数名,在括号里加入具体的参数。此时的参数不再是定义函数时的符号,而是一个实际的数据—字符串"Hello World!"。所以,在函数调用时出现的参数称为实参(argument)。
函数print()返回值为None,所以我们并不关心这个返回值。但如果一个函数有其他返回值,那么我们可以获得这个返回值。一个常见的做法是把返回值赋予给变量,方便以后使用。下面程序中调用了square_sum()函数:
x =square_sum(3,4)
print(x) # 结果为25
Python通过参数出现的先后位置,知道3对应的是函数定义中的第一个形参a,4对应第二个形参b,然后把参数传递给函数square_sum()。函数square_sum()执行内部的语句,直到得出返回值25。返回值25赋予给了变量 x ,最后由print()打印出来。
函数调用的写法,其实与函数定义第一行def后面的内容相仿。只不过在调用函数时,我们把真实的数据填入到括号中,作为参数传递给函数。除具体的数据表达式外,参数还可以是程序中已经存在的变量,比如:
a = 5
b = 6
x = square_sum(a, b)
print(x) # 结果为61
4.函数文档
函数可以封装代码,实现代码的复用。对于一些频繁调用的程序,如果能写成函数,再每次调用其功能,那么将减少重复编程的工作量。然而,函数多了也会有函数多的烦恼。一个问题常见就是,我们经常会忘记一个函数是用来做什么的。当然,我们可以找到定义函数的那些代码,一行一行地读下去,尝试了解自己或别人在编写这段程序时的意图。但这个过程听起来就让人痛苦。要想让未来的自己或他人避免类似的痛苦,就需要在写函数时加上清晰的说明文档,说明函数的功能和用法分别是什么。
我们可以用内置函数help()来找到某个函数的说明文档。以函数max()为例,用这个函数用来返回最大值。比如:
x = max(1, 4, 15, 8)
print(x) # 结果为15
函数max()接收多个参数,再返回参数中最大的那一个。如果一时想不起来函数max()的功能和所带的参数,那么我们可以通过help()来求助。
>>> help(max) # 以下为help()运行的结果,也就是max()的说明文档。
Help on built-in function max in module __builtin__:
max(...)
max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.
(END)
可以看到,函数max()有两种调用方式。我们之前的调用是按照第二种方式。此外,说明文档还说明了函数max()的基本功能。
函数max()属于Python自身定义好的内置函数,所以已经提前准备好了说明文档。对于我们自定义的函数,还需要自己动手。这个过程并不复杂,下面给函数square_sum()加上简单的注释:
def square_sum(a,b):
"""return the square sum of two arguments"""
a = a**2
b = b**2
c = a + b
return c
在函数内容一开始的时候,增加了一个多行注释。这个多行注释同样有缩进。它将成为该函数的说明文档。如果我用函数help()来查看square_sum()的说明文档,则help()将返回我们定义函数时写下的内容:
>>>help(square_sum)
Help on function square_sum in module __main__:
square_sum(a, b)
return the square sum of two arguments
通常来说,说明文档要写得尽可能详细一些,特别是人们关心的参数和返回值。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论