在前面已经多次提到函数这个概念,之所以没有解释什么是函数,是因为程序中的函数和数学中的函数差不多,如input()、range()等都是函数,这些都是Python的标准函数,直接使用就可以了。根据需要,用户也可以自定义函数。 12。1函数 函数的结构: def函数名(参数): 函数体 return返回值 例如:数学中的函数f(x)2x5在Python中可以定义如下: deff(x): y2x5 return(y) 如果x取值为3,可以使用如下语句调用函数: f(3) 下面给出完整的程序代码: deff(x): y2x5 return(y) resf(3) print(res) 运行结果:11 如上例中的x是函数f(x)的参数,有时也被称为形式参数(简称形参),在函数被调用时,x被具体的值3替换y就是函数的返回值,这个值3也被称为实际参数(简称实参)。 上例中的y是函数f(x)的返回值。并不是所有的函数都有参数和返回值。如下面的函数: deffunc(): print(此为无参数传递、无返回值的函数) func() 输出结果:此为无参数传递、无返回值的函数 可以看出,该函数func()无参数,故调用时不用赋给参数值。 函数也可以有多个参数,如f(x,y)xy,可用Python语言定义如下: deff(x,y): zx2y2 returnz print(f(2,3))调用函数f(x,y) 输出结果:13 也可以通过直接给参数列表中的参数赋值的方法,为参数添加默认值,如果用户赋予参数值,则按照用户赋值执行,否则使用默认值。例如: deff(x,y3): zx2y2 returnz 若调用时参数列表为(2,1),即x赋值为2,y赋值为1: print(f(2,1)) 输出结果为:5 若调用时参数列表为(2),即x赋值为2,y赋值省缺,则y使用默认值: print(f(2)) 输出结果为:13 回调函数,又称函数回调,是将函数作为另一函数的参数。 例如: deffunc(fun,m,n): fun(m,n) deffadd(m,n): print(mn,mn) deffmult(m,n): print(mn,mn) func(fadd,2,3) func(fmult,2,3) 输出结果: mn5 mn6 在fadd(m,n)和fmult(m,n)被定义前,func(fun,m,n)中的fun(m,n)就已经调用了这两个函数,即先调用后定义,这也是回调函数的特点。 如果无法预知参数的个数,可以在参数前面加上号,这种参数实际上对应元组类型。譬如,参会的人数事先不能确定,只能根据与会人员名单输入: deffunc(names): print(今天与会人员有:) fornameinnames: print(name) func(张小兵,陈晓梅,李大海,王长江) 运行后,输出结果为: 今天与会人员有: 张小兵 陈晓梅 李大海 王长江 参数为字典类型,需要在参数前面加上号。 deffunc(kwargs): foriinkwargs: print(i,kwargs〔i〕) func(aa1,bb1,cc1) 输出结果为: aa1 bb1 cc1 一个有趣的实例: deffunc(x,y,z,args,kwargs): print(x,y,z) print(args) print(kwargs) func(a,b,c,Python,iseasy,pypython,jjava,phphp) 输出结果: abc前三个实参赋给前三个形参 (Python,iseasy)args接收元组数据 {py:python,j:java,ph:php}kwargs接收字典数据 12。2变量的作用域 变量的作用域即变量的有效范围,可分为全局变量和局部变量。 局部变量 在函数中定义的变量就是局部变量,局部变量的作用域仅限于函数内部使用。 全局变量 在主程序中定义的变量就是全局变量,但在函数中用关键字global修饰的变量也可以当做全局变量来使用。 全局变量的作用域是整个程序,也就是说,全局变量可以在整个程序中可以访问。 下面通过实例去讨论: 程序1: a1a为全局变量 defaadd(): print(a的初值:,a)在函数中读取a的值 aadd()调用函数aadd() a1主程序语句,a增加1 print(a现在的值是:,a)主程序语句,读取a的值 运行结果: a的初值:1 a现在的值是:2 这个结果和我们想象的一样,全局变量a既可以在主程序中读取,也可以在子程序(函数)中读取。 程序2: a1 defaadd(): a1 print(a的初值:,a) aadd() print(a现在的值是:,a) 运行程序1时出现如下错误提示: UnboundLocalError:localvariableareferencedbeforeassignment 意思是:局部变量a在赋值之前被引用。 从语法上来讲,该程序没有错误。首先定义了一个全局变量a并赋值为1,又定义了一个函数aadd(),函数内的语句a1就是出错的根源,虽然我们的初衷是想让全局变量a的值增加1,但从错误提示看,这个语句中的a并不是全局变量,而是局部变量。看来,在函数中读取全局变量的值是没有问题的(在程序1中已经得到了验证),但要在函数中改变全局变量的值是不行的(在程序2的错误提示a1中的a是局部变量,而非全局变量)。 怎样解决这个问题? 程序3: a1 defaadd(x): x1 returnx print(a的初值:,a) aaadd(a) print(a现在的值是:,a) 运行结果: a的初值:1 a现在的值是:2 结果的确是正确的,但在函数aadd(x)中没有调用变量a(没有出现变量a)。 程序4: a1 defaadd(a): a1 returna print(a的初值:,a) aaadd(a) print(a现在的值是:,a) 运行结果: a的初值:1 a现在的值是:2 对比程序4和程序3不难发现,其实程序4只是简单的把函数的参数x变成了a,这个a的实质和程序3中的x还是一样的。这进一步证实,函数中的a是局部变量,与主程序的全局变量a有着本质的区别。 程序5: a1 defaadd(): globala a1 print(a的初值:,a) aadd() print(a现在的值是:,a) 运行结果: a的初值:1 a现在的值是:2 程序5和程序2相比较,仅仅是在函数中添加了一个定义globala,此时的局部变量a就可以当做全局变量使用,由于它和全局变量a同名,自然也就不用区分a究竟是全局变量还是局部变量了,在主程序和该函数内都可以访问、修改变量a的值了。 虽然使用global可使变量使用起来非常方便,但也容易引起混淆,故在使用过程中还是谨慎为好。 12。3函数的递归与嵌套 递归,就是函数调用它自身。递归必须设置停止条件,否则函数将无法终止,形成死循环。 以计算阶乘为例: deffunc(n): ifn1: return1 else: returnnfunc(n1)func()调用func() print(func(5)) 运行结果为:120 嵌套,指在函数中调用另外的函数。这是程序中常见的一种结构,在此不再赘述。 匿名函数 Python中可以在参数前加上关键字lambda定义一个匿名函数,这样的函数一般都属于一次性的。 例如: 程序1:这是一个常规的函数定义和调用。 deffadd(x,y): returnxy print(fadd(2,3)) 输出结果:5 程序2:使用lambda定义匿名函数。 faddlambdax,y:xy print(fadd(2,3)) 输出结果:5 从上面的代码可以看出,使用lambda仅仅减少了一行代码。faddlambdax,y:xy中的fadd不是变量名,而是函数名。程序1和程序2的print()语句中的参数都是一样的调用函数fadd()。所以,匿名函数并没有太多的优点。