7.1 函数概述
函数的概念:函数是可以重复使用的、实现特定功能的代码段。函数可以通过函数名进行调用,并通过参数传递获得期望的返回值。
模块化思想和实现:虽然从理论上讲,可以将一个程序中的全部代码都放在一起,但这并不适用于大型程序的构建。开发和维护一个大型程序的有效方法就是采用“分治”的思想,将其划分为若干个程序模块,每个模块用来实现一个特定的功能。Python用函数来实现模块的构建,并通过函数调用将其组成一个有机的整体。避免重复代码:使用函数,避免程序中重复的代码,提高了程序的编写、调试和维护的效率。实现代码的复用:用户编写的函数,可以在多个程序中使用。
Python中函数的分类:
内置(建)函数
模块内函数(内置模块和第三方模块)
自定义函数
7.2 函数的定义和调用
1、函数定义:
2、函数的调用:
3、函数的返回值
函数的返回值就是函数执行以后返回到主调函数的结果,在函数体内通过return语句实现。
语法格式:return 返回值
在函数体内执行了return语句后,该函数将结束,把控制权转向主调函数,因此,return语句还为函数提供了一个出口。在函数体内允许有多个return语句,无论执行了哪一个,都将结束该函数的执行。Python函数中的return语句可以同时返回多个值,各值之间用逗号分隔。调用函数时,所得到的这些返回值会被作为一个元组中的元素。有的函数的功能不是计算结果,而是完成某项特定的任务(如打印数据,绘制图形等),执行完后不返回结果,可以没有return语句。函数没有return语句或return语句无返回值,调用时函数都将返回None。None是Python中一个特殊的值,它不表示任何数据。返回值是None的函数,在被调用时一般都单独作为一行语句,其功能是完成特定的任务,而不是计算一个结果。
示例1:函数的定义与调用
关于函数内部的if __name__=='__main__'
7.3 函数的参数
1、参数概述:
定义函数时,参数的名字和位置确定下来,函数的接口就固定了。对函数的调用者而言,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来。
参数:是调用函数的语句和被调函数之间信息交互的载体。函数的参数分为形式参数和实际参数两种。
形式参数: 函数定义时,写入圆括号内参数列表中的参数称为形式参数,简称形参(parameter) 。函数被调用之前,形参没有具体的值。
实际参数:函数调用时,写入函数圆括号内参数列表中的参数称为实际参数,简称实参(argument)。实参可以是常量、变量或表达式,有具体的值。
参数传递:在函数调用过程中,若被调函数是有参函数,则在调用函数的语句和被调函数间存在着参数的传递。函数调用的时候,实参会把值传递给形参,就实现了参数的传递。
Python中,一切都是对象,参数也是对象,实参变量保存的值是对象的引用,参数传递就是实参将对象的引用传递给形参,这样,实参和形参都指向同一个对象(形参可以看做是实参的别名)。
2、形参的设计
如何确定形式参数的个数、位置和类型,这是一个常令初学者困惑的问题。事实上,形参的设计与函数的预期功能密切相关。函数要实现相应的功能,必须获得一定的原始信息,而这些原始信息主要来自形参,因此形参的设计应从分析函数的功能入手。
根据要实现的功能,函数可分为两种形式:有参函数和无参函数。为了实现函数的功能,需要向函数传递必要的信息的是有参函数;无需向函数传递信息,就可以实现函数的功能的是无参函数。
3、参数类型:
Python函数的参数类型较为丰富,参数定义的灵活度大。参数的类型主要包括:位置参数、关键字参数、默认参数、可变数量参数等。
a.位置参数:
位置参数:也称必选参数,顺序参数,是最重要的一种参数类型。位置参数是在调用函数时必须明确提供的参数,这种类型的参数必须按照先后顺序,一一对应进行匹配。
b.关键字参数
为了避免参数过多容易调用时产生位置混乱,函数调用时,实参可以指定对应形参的名字。此时实参的顺序可以与定义时形参的顺序不同,也就是说,关键字参数允许函数调用时实参的位置和顺序与定义时形参的位置和顺序不一致。
c.默认参数
也称缺省值参数。定义函数时,可以为某些形参设置默认值。在调用该函数时,就可以省略相应的实参,函数会使用形参的默认值来替代实参的值;若调用函数时提供了实参,则按照实参的值进行传递。
4、参数传递方式
参数传递:形参之所以成为形参,是因为函数被调用之前,形参并没有具体的值。函数调用过程中,调用函数的语句和被调函数间存在着参数的传递这时实参会把值传递给形参,从而实现参数的传递。
Python中,一切都是对象,参数也是对象,实参保存的值是对象的引用,参数传递就是实参将对象的引用传递给形参,这样,实参和形参都指向同一个对象(形参可以看做是实参的别名)。
传统语言中,参数的传递方式主要有按值传递(call by value,得到实参的副本)和按引用传递 (call by reference ,得到实参的指针)两种方式。对于Python,我们可以这样说,”参数按值传递,但这里的值是对象的引用“,即函数得到实参的副本,但参数始终是引用。若实参引用的对象是可变对象,且在函数执行过程中改变了这个对象,实参对象就将发生变化。但函数内部对形参进行重新赋值(重新绑定),将不会对实参对象造成影响。
有人将Python的这种参数传递方式称为共享传参(call by sharing),指函数的形式参数获得对应实参中各引用的副本, 即函数内部的形参是实参的别名。
5、可变对象和不可变对象
Python在堆(heap)中分配的对象可以分成两类:可变对象和不可变对象。所谓可变对象,是指对象的内容可变,具体包括列表list、字典dictionary等;不可变对象,是指对象的内容可变,包括整数int、浮点数float、字符串string、元组tuple等。
对于+=、*=等增量赋值,若左边的变量绑定的是不可变对象,就会创建新对象;若边的变量绑定的是可变对象,就将修改这个对象。
由于参数是以别名的形式传递,这意味函数可能会修改通过参数传入的可变对象,除非在本地为可变对象创建副本或使用不可变对象。
7.4 变量的作用域
1、变量作用域的概念
变量的作用域(scope):指变量在程序中能够被访问的区域,即在哪个范围内,可以使用该变量。变量作用域由变量定义的位置决定。
Python中没有专门定义变量的语句,它规定赋值即定义。也就是说,第一次对变量赋值,就是对变量的定义。所有变量都需要先定义(先赋值)后使用。
若程序中含有自定义函数,代码的位置就分为函数内部代码和外部代码两种情况。根据变量定义所处位置的不同,可分为两类变量:全局变量和局部变量。
全局变量:全局变量一般在函数外部定义,必要时也可在函数内部使用global关键字定义全局变量。全局变量的作用域是整个程序。
局部变量: 在函数内部定义的变量称为局部变量(数定义中的形式参数也是局部变量),其作用域是定义它的函数的内部。
7.5 程序举例
示例1:素数问题-改进判别素数的函数
示例2:素数问题-寻找回文素数
回文指数或字符串具有首尾回环性质,从后向前逆序后与原文一样。例如123321,就是一个回文数。编写一个函数,调用前面定义好的素数判定函数完成回文素数的判定,函数无返回值,直接输出。