购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.4 函数

为了让程序的代码更加简洁,一个较大的程序应分为若干个程序模块,每一个模块用来实现一个功能。Python语言中,可以将一段需要经常使用、能够实现一定功能的代码段封装起来,在需要使用时可以直接调用,这就是程序中的函数。这体现的是结构化程序设计思想,即“分解”大问题,依次解决小问题,通过小问题的解决实现大问题的解决,描述“小问题”解决方法的工具即是函数。总而言之,函数可以实现特定的功能,提高代码复用率。

2.4.1 函数定义及调用

无参函数的一般形式如下:

创建好了一个函数,该怎么调用该函数呢?其实调用函数很简单,直接写出函数名加上后面的小括号即可。接下来通过一个例子来帮助读者理解如何调用函数。具体实现代码如下。

程序清单2-33 函数定义实例

该程序运行后,结果如下。

有参函数的一般形式如下:

可以看出有参函数与无参函数的区别是在后面的括号里是否加了参数。在定义函数时,把函数参数的名字和位置确定下来,函数的接口也就确定了。在使用别人写好的函数时,应知道函数的名称、各个参数的意义及该函数的返回值。接下来通过一个例子,体会一下带有参数的函数是如何定义和调用的。

任意输入一个数字,要求输出该数的三次方。具体代码实现如下。

程序清单2-34 函数使用实例

该程序运行后,结果如下。

有时候,需要函数给返回该函数执行后的结果,可以通过关键字return实现。例如,在上面的例子中,可以通过return语句直接返回计算后的结果。具体代码实现如下。

程序清单2-35 带返回结果函数实例

该程序运行后,结果如下。

2.4.2 参数与变量

在2.4.1节中,介绍了有参函数,在本节中将具体介绍函数的参数。

1.位置参数

调用含多个形参的函数时,实参的值将按照位置顺序依次赋给形参。可以结合下面的代码一起理解位置参数的含义,具体代码实现如下。

程序清单2-36 带参数函数实例

该程序运行后,结果如下所示。

上述代码中定义了带有两个形参的函数pow,在调用该函数时实参2和4按照顺序依次赋值给形参,最后函数返回乘法运算的结果。

2.可变参数

在定义参数时,在参数前面加上一个*,参数的个数可变。

可变参数允许传入任意多个参数,这些参数将在函数调用的时候自动组装成一个元组。例如,计算一组数字的平方和是多少,就可以用可变参数来实现。具体实现代码如下所示。

程序清单2-37 带可变参数函数实例

该程序运行后,结果如下所示。

上述代码中定义了带可变参数的函数sum,其功能是对输入任意个参数求平方和。

3.关键字参数

可以传入任意多个含参数名的参数。

关键字参数允许传入任意多个含参数名的参数,这些关键字参数将在函数调用时自动组装成一个字典。可以通过以下代码理解关键字参数。

程序清单2-38 带关键字参数函数实例

该程序运行后,结果如下。

在函数的调用中,一定要注意形参与实参的关系。接下来,将用一个例子使读者能够对形参和实参的关系有进一步的理解。这个例子是用一个函数交换两个数字的值,具体代码实现如下。

程序清单2-39 形参实参理解实例

读者可以猜一猜调用这个函数后,输出的结果是多少?很多人会回答32,其实答案是23,这是为什么呢?因为数值是不可更改对象,形参的交换并不会影响到实参。

在使用函数时,一定要注意形参在什么时候才会影响实参。在Python中,string(字符串)、tuples(元组)和number(数值)都是不可更改对象,即形参的变化不会改变实参的值;而list(列表)、dict(字典)等则是可以更改的对象,即形参的变化可以改变实参的值。

温馨提示:

在使用函数参数的时候,要注意形参影响实参的一些情况。如果形参是数值类型,形参的改变并不会影响实参的值,读者在使用的时候要注意。

4.局部变量和全局变量

(1)局部变量的作用域是定义该变量的子程序。如函数中定义的变量就是局部变量,该变量的作用域只在函数的范围内,超出该函数,这个变量就是无效的。

(2)全局变量的作用域是整个程序。

可能有人会问,如果全局变量和局部变量同名,会怎么样呢?这种情况下,在定义局部变量的子程序中,局部变量起作用,在其他地方全局变量起作用。对于初学者来说,很容易在这方面出错,因此在给变量命名时要注意避免这种情况发生。

如果在函数中试着修改全局变量会发生什么呢?接下来,请分析下面的代码。

程序清单2-40 全局变量局部变量理解实例

读者可以猜测一下现在得到的结果是什么?可以将下面的正确答案和自己的答案进行对比。上述程序运行后,结果如下。

为什么会出现上述结果呢?这是因为全局变量的作用域是整个代码,当我们试图在函数中改变全局变量时,函数中会生成一个变量名和全局变量相同的变量,在函数中改变的是这个新生成的变量,而真正的全局变量并不会被改变,所以得到的结果如上述所示。

2.4.3 递归函数

在编程语言中,函数直接或间接地调用函数本身的行为叫作递归。

下面来看一个小兔子生成的例子:有一对小兔子,过一个月它们就会长成大兔子,大兔子过一个月就会生一对小兔子,小兔子过一个月又会长成一对大兔子,大兔子每过一个月都要生出一对小兔子。照这样生下去,且假定兔子无死亡,问5个月后应该有多少只兔子?

图2-1给出了兔子繁殖的规律,从第三个月开始,每个月的兔子都为前两个月兔子数量之和。按照这个规律可以得到一个数列:1 1 2 3 5 8 13 21 34 55……,这个数列也被称为斐波那契数列。该如何用程序语言实现上述问题呢?可以通过递归函数解决上述问题。在编写一个递归函数的时候,需要设置合适的终止条件,否则该函数就会一直调用自己无法结束,最后导致程序崩溃。在上述兔子问题中,可以看到当月份等于1或2的时候,直接返回兔子的数量1,而不是继续调用函数,这个就是该递归函数的结束条件。遵循该思路,现在来编写这个递归函数,代码实现如下。

图2-1 兔子问题分析

程序清单2-41 递归函数实例

该程序运行后,结果如下。

上述程序中的递归过程如图2-2所示。

图2-2 递归分析过程

图2-2清晰地给出了上述程序递归调用的整个流程,可以看到整个递归过程的调用情况,递归函数逐渐向下调用,遇到递归函数的结束条件后再逐层向上返回得到的数据,最后得到结果。 BgGlWWfkkZwm+Zky4ATOlQgx7J/B8sWFSlKOOwJRf9MKRFZqNCCiTdCIcW4PDxno

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开