我们回忆一下,在前面章节里,我们使用最多的有两个函数,一个是print,一个是input,两者分别解决了我们最为常见的输出和输入功能。但是我们知道这些函数是怎么实现的吗?我们其实也不必知道,只需使用它们就行了。而且对它们的使用也比较灵活,给它们不同的参数,它就会做不同的事情,比如:
print('Hello!')
print('Bye!')
输出为:
Hello!
Bye!
你传递给print不同的字符串,它就会输出不同的字符串,这个跟在函数名称后圆括号中的数据被称为参数,所以函数通过参数实现定制化的功能。
由此我们可以看出函数最大的意义就在于提供了一种供别人使用的扩展功能,别人只需直接调用这些函数即可使用,而无需知道如何实现,显然这非常方便。借助于互联网上大量别人开发好的函数,我们几乎可以无限扩展自己代码的功能。
那么我们可以将自己的代码给别人使用吗?也像这样通过函数,甚至允许参数来进行。
我们从一个例子开始。比如我们判断两个数的最大值并输出。这是完整的代码:
if 1 > 2:
print(1)
else:
print(2)
这里我们没有使用变量,就直接比较两个固定的常量,但是代码的逻辑是可以比较任何两个数值,并输出最大的数值。
假设这段代码经常需要在程序中被使用,甚至还需要提供给其他人用。显然直接将代码复制来复制去不是一个好主意。比如首先代码复制过去后,会和当前代码融为一体,增加对代码功能理解的复杂度,更为麻烦的是,如果想修改,就要将所有复制过去的代码都要改动。而且有时你可能还想拥有代码保护的权力,虽然允许别人使用,但是并不想把代码给别人看到。
所有这一切都说明,你需要使用函数了。怎么使用呢?很简单!把你需要分享的代码拿出来,按照下面的写法定义下:
def func():
if 1 > 2:
print(1)
else:
print(2)
定义方法也很简单,就是将全部代码先缩进,表示这些代码都是所定义函数的内部代码。然后在首部写上def,表示“definition”,定义的意思,然后就是一个函数名称,之所以定义名称,是因为我们可以定义很多不同的函数,通过这些不同的函数名称就可以很好的区分,正如通过变量名称区分不同变量一样。
接下来,需要在函数名称后加上个圆括号,为什么要加?一是为了和变量区别,否则在使用时,函数和变量就都像一个样子。有了这个区别,我们在使用函数时,总需要跟着这个圆括号,即使里面什么参数都不需要写;二是为了以后添加参数,这个我们后面会很快看到如何使用。
既然可以调用,就以随意多次的调用,很方便:
def func():
if 1 > 2:
print(1)
else:
print(2)
func()
# ...
func()
运行界面为:
使用方法很简单,就像以前使用print和input函数一样,直接书写函数名称加圆括号就可以。请注意,一定要在函数定义后才能使用函数,否则系统会提示函数没有定义。
但是这个函数有点太简单了,功能固定,能不能灵活些呢?比如就像print函数一样,我们假设可以传递两个整数,此时,我们也希望它们都能得到正确的最大值输出:
可以做个比喻,如果把这些新加的数值看成是礼物,现在的主要问题是让函数把礼物收下来。为此函数必须拿出两个盘子来装,由于变量可以存储数值,我们可以想象函数自己在圆括号里放上两个变量来表示两个盘子:
这里看的出来num1和第一个整数对应,num2和第二个整数对应。此时就可以把过去函数中的两个常量1和2分别换成num1和num2,它们就是函数的参数。所谓函数参数,就是用于接收传递给函数不同数值的变量,定义的位置位于函数名称的括号内。为了区分,我们把定义在函数圆括号里面的、接受外部数据的参数称之为形式参数(简称为形参),把调用函数时写在圆括号里面的、赋给函数数据的参数称之为实际参数(简称为实参)。
现在可以将函数代码中的常量也对应的替换:
def func(num1, num2):
if num1 > num2:
print(num1)
else:
print(num2)
func(1, 2)
func(2, 4)
func(3, 2)
运行界面为:
你会发现现在程序就可以运行了!而且真的可以输出你所传递过来的两个任意整数的最大值:
请注意,数值的次序很重要,第一个数值就会传给第一个函数参数,以此类推。如果你想改变这个次序,可以通过强制在数值前增加要赋值的参数名称来实现:
def func(num1, num2):
if num1 > num2:
print(num1)
else:
print(num2)
func(num2=1, num1=2)
输出为:2。这种方法中的赋值参数也被称为“关键字参数”。相对而言,传统那种靠位置次序来表达的参数称之为“位置参数”。
目前的版本还不错,但是我们可以继续考虑方便性。首先,这个func的函数名称太不清楚,不如起个max见名知义的好名称:
def max(num1, num2):
if num1 > num2:
print(num1)
else:
print(num2)
max(1, 2)
max(2, 4)
max(3, 2)
其次,如果现在我们想比较两个整数,将最大值保留到一个其他变量中去。我们可以使用这个函数吗?虽然这个函数max可以求出两个参数的最大值,但是它只能输出到屏幕上!
显然这不是一个好主意。想想看,在很多时候我们都希望能更为灵活的处理最大值。退一步说,既然max是最大值,它能求出最大值就可以了,为什么还要输出到屏幕上?不能输出到打印机上?文件中?变量中?其实这个输出不应该作为这个函数功能的一部分。它只要能求出并把它交出来就可以了。
就像刚才参数传递一样,也需要两个步骤:
第一步是这个函数要把值交出来:这个return语句表示函数交出一个数值,也称为返回值,和return单词字面的返回含义一致。
第二步就是需要在调用函数的时候,接收这个值。我们既然可以直接输出最大值,也可以保存到其他变量中再做进一步处理等等。调用者可以自己决定如何使用这个最大值。
显然,此时对于这个函数整体而言,你可以把它就想象成一个唯一的数值即可,这个数值就是此时函数的返回值。不同于一般的数值,这个数值会因为函数参数的不同和功能的不同而呈现出变化的特点。
有了这种函数的封装,程序按照功能一块一块拆分开来,形成不同的函数,到了使用的时候,通过函数名称来调用,甚至可以通过参数和返回值实现必要的数据传递,代码的可读性和模块化都更为明显。
配套学习资源、慕课视频: