资源描述
第5章函数设计与使用函数在实际开发中,有许多操作时完全相同或非常相似的,仅仅是要 处理的数据不同,为此需要实现代码复用。函数:可能需要反复执行的代码封装为函数,并在需要该段代码 功能的地方调用。可以实现代码的复用 更重要的是可以保证代码的一致性,只需要修改该函数代码,则所有调 用均受到影响 Python包括常用的内置函数如len(),sum()等,也可以自定义函数。另一种代码复用方式:定义面向对象程序设计中的类5.1函数定义与调用5.1函数定义与调用创建或定义函数要使用def关键字 函数定义(声明)格式:def函数名(形参列表):,注释,,函数体函数调用:函数名(实参列表)注意:1 1def fib(n):accept an integer n.return the numbers less than nin Fibonacci sequence.a,b=1,1while a def fib(n):函数定义(声明)格式:acceptdef函数名(形参列表):、注媒accept an integer n.return the numbers less than n m Fibonacci sequence.b=1,1函数体while a fib(1 000)#函数调用4 在定义函数时,开头部分的注释并不二05金。3,,43匕5.5金也巨”二也-6,1。987的话,可以为用户提供友好的提示和使用帮助。u fib(n):art A*L*A.r W*Xm 4 J return zhe numters less rhan n in Fitanacci sequence.a,b=1,1J _e a jLb(|(n)accept an integer n.return the numbers less than n in Fibonacci sequence.这样,在调用该函数是,输入左侧圆括号之后,立即就会得到该 函数的使用说明5.1 函数定义与调用 def fib(n):accept an integer n.函数调用:函数名(实参列表)return the numbers less than n in Fibonacci sequence.,a,b=1,1while a fib(1 000)#函数调用注意:1 1 2 3 5 8 1 3 21 34 55 89 1 44 233 377 6 1 0 987函数体相对于def关键字必须保持一定的空格缩进,是函数执行的代码块函数可以返回值,也可以不返回。如果函数体中包含return语句,则返回值,否则不返回,即返向值为空(N one)函数调用时,根据需要,可指定实际传入的参数值。5.2形参与实参5.2形参与实参函数定义(声明)格式:def函数名(形参列表):,注释,函数体函数调用:函数名(实参列表)形参 def fib(ll):accept an integer n.return the numbers less than n m Fibonacci sequence.1 1 2 3 5 8 1 3 21 34 55 89 1 44 233 377 6 1 0 9875.2形参与实参定义函数时,对参数个数没有限制,逗号进行分隔。如:编写函数,接受两个整数,并输出其中最大数。printMax(a,b):if ab:pirnt(a,is the max)else:print(b,is the max)如有多个形参,则需要使用 printMax(3,4)4 is the max注意:这个程序并不是很好,如果输入 的参数不支持比较运算,会出错。5.2形参与实参函数调用时向其传递实参,将实参的值或引用传递给形参。绝大多数情况下,在函数内部直接修改形参的值不会影响实参 def addOne(a):print(a)a+=1print(a)a=3 addOne(a)34 a35.2形参与实参在有些情况下,可以通过特殊的方式在函数内部修改实参的值 def modify(v):#修改列表元素值 v 0=v 0+1 def modify(v,item):#为列表增 加元素v.append(item)a=2 modify(a)a 3 a=2 modify(a,3)a 2,3 def modify(d):#修改字典元素值 最为字典增加元素d age=38 a=name:Dong,age:37,sex:Male)a sex:Male,age:37,name:Dong,modify(a)a sex:Male,age:38,name:Dong,注意:如果传递给函数的是Python可变序列,并且在函数内部使用下标或其他方式为可变序列增加、删除元素或修改元素值时,可以使得实参得到相应的修改。5.3参数类型5.3参数类型在Python中,函数参数有很多种:普通参数 默认值参数 关键参数 可变长度参数等等。Python函数的定义非常灵活,在定义函数时不需要指定参数的类型,形参的类型 完全由调用者传递的实参类型以及Python解释器的理解和推断来决定;函数编写如果有问题,只有在调用时才能被发现,传递某些参数时执行正确,而 传递另一些类型的参数时则出现错误。def say(message,times=1):print(message*times)5.3.1默认值参数 Python在定义函数时,支持默认值参数,即可为形参设置 默认值。def函数名(,形参名二默认值)函数体 调用带有默认值参数的函数时,可以不对默认值参数进行 赋值,也可以赋值,具有较大的灵活性。使用“函数名._defaults_”以元组的形式查看函数所有 默认值参数的当前值 say(hello)#不为默认值参数传值 hello say(hello,3)#使用调用者显示传递的值 hellohellohello say(hi,7)#使用调用者显示传递的值 hihihihihihihi say.defaults_(1,)5.3.1默认值参数默认值参数必须出现在函数参数列表的最右端,且任何一个默认值参数右边不能有非默认值参数。(a=3,b,c=5):a,b,cSiTitaxError:non-defsuit argLnnenL follows default argLnnent 七 f(a=3,b):prmr a,bSioitaxError:non-de fault arginnenL follows default argnmerrc w f(azbr c=5):r r i:r a,b,c5.3.1默认值参数例:使用指定分隔符将列表中所有字符串元素连接成一个字符串,默认空格。def Join(List,sep=N one):return(sep or ).join(List)aList=a,b,,c Join(aList),a b c,Join(aList,)a,b,c5.3.1默认值参数默认值参数如果使用不当,会导致很难发现的逻辑错误。def demo(newitem,old_list=):old.list,append(newitem)return old_list print(demo(5,1,2,3,4)ttright 1,2,3,4,5 print(demo(aaa,a,b)bright a,,,b,aaa,print(demo(a)ttright print(demo(b)6 1-print(demo.defaults)(a,b,)注意:多次调用函数并且不为默认值参数传递值 时,默认值参数值用在第一次调用时进行解释,可 以使用函数名.defaults查看默认参数的当前值 如何修改?O5.3.1默认值参数修改程序如下:def demo(newitem,oldist二N one):if oldlist is N one:old_list=old list.append(newitem)return old_listprint(demo(5,1,2,3,4)Wright print(demo(aaa,a,b)Wright print(demo(a)Wright print(demo._defaults)print(demo(b)!+运行该程序,看看和前面的有什么不同?可以这么理解,当一个函数有一个默认参 数,并且默认参数是空的可变类型时(diet和list),该可变类型只初始化一 次,之后的每次操作,都在前一次的操作 基础上操作。但是对于默认参数是不可变 的类型时(tuple和字符串和数字),不 会有这种情况。5.3.2关键参数关键参数主要指实参,即调用函 数时的参数传递方式。通过关键参数可以按参数名字传 递值,实参顺序可以和形参顺序 不一致,但不影响传递结果,避 免了用户需要牢记位置参数顺序 的麻烦。def demo(a,b,c=5):print(a,b,c)demo(3,7)3 7 5 demo(a=7,b=3,c=6)7 3 6 demo(c=8,a=9,b=0)9 0 85.3.3可变长度参数可变长度参数在定义函数时主要有两种形式:*parameter:接收多个实参并将其放在一个元组中*parameter,接收字典形式的实参。def demo(*p):print(p)def demo(*p):for item in p.items():print(item)demo(1,2,3)(1,2,3)demo(1,2)(1,2)demo(1,2,3,4,5,6,7)(1,2,3,4,5,6,7)demo(x=l,y=2,z=3)Cz 3)(y,2)Cx 1)(1)aeeter无论调用该函数时传递了多少实参,一律将其放在元组中。(2)parameter调用该函数时自 动将接收的参数转换为字典。5.3.3可变长度参数几种不同类型的参数可以混合使用但是不建议这样做,易导致代码混乱而严重降低可读性,可能导致查错非常困难 def func_4(a,b,c=4,*aa,*bb):print(a,b,c)print(aa)print(bb)func_4(1,2,3,4,5,6,7,8,9,xx=,T,yy=2,zz=3)1 2 3(4,5,6,7,8,9)zzJ:3,,xx,:,,,yy,:,2,func_4(l,2,3,4,5,6,7,xx=1 ,yy=2,zz=3)1 2 3(4,5,6,7)zz,:3,,xx:,,,yy:,2 5.3.4参数传递的序列解包为含有多个变量的函数传递参数时,可以使用Python列表、元组、集合、字典以及其他可迭代对象作为实参,并在实参名称前加一个星号*,Python解释器将自动进行解包。def demo(a,b,c):print(a+b+c)seq=1,2,3 demo(*seq)6 tup=(l,2,3)demo(*tup)6 die=1:a,2:b,3:c demo(*dic)6 set=1,2,3 demo(*set)6 demo(*dic.values()abc5.4 return语句5.4 return语句 return语句用于从一个函数中返回并结束 函数的执行,同时还可以通过其从函数中 返回一个值。无论return语句出现在函数的什么位置,一旦得到执行将直接结束函数的执行。函数的返回值类型由return语句返回值的 类型来决定 如果函数没有return语句或者没有执行 return语句,执行了不带任何值的return 语句,则函数都默认为返回空值N one。def maxi mum(x,y):if xy:return xelse:return y theMax=maximum(3,4)print(theMax)4注意:这个程序并不是很好,如果输入 的参数不支持比较运算,会出错。5.4 return语句 在调用内置数据类型的方法时,一定要注意该方法有没有返回值。a_list=l,2,3,4,9,5,7 print(sorted(a list)1,2,3,4,5,7,9 print(a list)1,2,3,4,9,5,7 a_list=l,2,3,4,9,5,7 print(a list.sort()N one print(alist)1,2,3,4,5,7,9(1)具有返回值(2)没有返回值。5.5变量作用域5.5变量作用域变量起作用的范围称为变量作用域。.一个变量在函数外部定义和在函数内部定义,其作用域是不同的:局部变量全局变量局部变量的引用比全局变量速度快。5.5.1局部变量局部变量在函数内定义的变量只在 该函数内起作用函数结束时,其局部变量被自动删除。def demo():x=3y=4 print(x,y)demo()3 4 xTraceback(most recent call last):File/zz/,line 1,in xN ameError:name x is not defined yTraceback(most recent call last):File z/z/,line 1,in yN ameError:name y is not defined5.5.2全局变量全局变量:其作用域为全局的,能够同时作用于函数内外,通过global来定义。x=5 def demo():global xx=3y=4 print(x,y)demo()3 4 x3 yTraceback(most recent call last):File,line 1,in yN ameError:name y is not defined del x xTraceback(most recent call last):File,line 1,in xN ameError:name x is not defined 一个变量已在函数外定义,如果在函数内 需要为这个变量赋值,并要将这个赋值结 果反映到函数外,可以在函数内用global 声明这个变量,将其定义为全局变量。5.5.2全局变量全局变量:其作用域为全局的,def demo():global x x=3 y=4 print(x,y)demo()3 4 x3 yTraceback(most recent call last):File,line 1,in y能够同时作用于函数内外,通过global来定义。在函数内部直接将一个变量声明为全局 变量,在函数外没有声明,在调用这个 函数之后,将增加为新的全局变量。I_N ameError:name y is not defined5.5.2全局变量示例pi=3.141592653589793e=2.718281828459045def my_func():global pipi=3.1 4print global pi=,,pi)e=2.71 8print(local e=,e)print(?module pi=,,pi)print C module e=,e)my_func()print C module pi=,,pi)print C module e=,,e)module pi=3.141592653589793 module e=2.718281828459045 global pi=3.14local e=2.718module pi=3 14module e=2.7182818284590455.6 lambda表达式(自学)5.6 lambda表达式 lambda表达式用来声明匿名函数,即没有函数名字的临时使用的小函数,只可以包 含一个表达式,且该表达式的计算结果为函数的返回值。不允许包含其他复杂的语句,但在表达式中可以调用其他函数。f=lambda x,y,z:x+y+zprint(f(1,2,3)64 8g=lambda x,y=2,z=3:x+y+zprint(g(2,z=4,y=5)115 6L=(lambda x:x*2),(lambda x:x*3),(lambda x:x*4)print(L 0(2),L 1(2),L 2(2)16D=fT:(lambda:2+3)f2:(lambda:2*3)f3:(lambda:2*3)print D fl(),D f2(),D f3()8含有默认参数,调用时使用关键参数5.6 lambda表达式 lambda表达式不允许包含其他复 杂的语句,但在表达式中可以调 用其他函数。1 X1,2,3,4,5 print(map(lambda x:x+1 0),L)1 1,1 2,1 3,1 4,1 5没有名字的1 ambda表达式 L 1,2,3,4,5 def demo(n):return n*n demo(5)25 a_list=l,2,3,4,5 list(map(lambda x:demo(x),a_list)1,4,9,1 6,25 没有名字的1,、包含函数的lambda表达式5.6 lambda表达式 lambda表达式其他示例 data=range(20)0,4,0,0,print data1,2,3,4,5,6,7,8,9,1 0,1 1,1 2,1 3,1 4,import randomrandom,shuffle(data)data3,1 1,1 3,1 2,1 5,9,2,1 0,6,1 9,1 8,1 4,8,data,sort(key=lambda x:x)data1,2,3,4,5,6,7,8,9,1 0,1 1,1 2,1 3,1 4,data,sort(key=lambda x:len(str(x)data1,2,3,4,5,6,7,8,9,1 0,1 1,1 2,1 3,1 4,data,sort(key=lambda x:len(str(x),reverse=True)data1 5,0,1 5,1 5,1 6,7,5,1 6,1 6,1 0,1 1,1 2,1 3,1 4,1 5,1 6,1 7,1 8,1 9,0,1,2,3,4,5,1 7,1 8,1 7,1,1 7,1 8,1 7,1 8,6,7,8,1 91 6 1 91 995.7案例精选5.7案例精选例1:编写函数计算圆的面积。from math import pi as PI import typesdef CircleArea(r):if isinstance(r,int)or isinstance(r,float):#确保接收的 参数为数值return PI*r*relse:print(J You must give me an integer or float as radius.)28.274333882308138print(CircleArea)5.7案例精选例2:编写函数,接收任意多个实数,返回一个元组,其中第一个元素为所 有参数的平均值,其他元素为所有参数中大于平均值的实数。def demo(*para):avg=sum(para)/len(para)#注意Python 2.x与Python 3.x对除法运算符 的解释不同g=i for i in para if iavgreturn(avg,)+tuple(g)print(demo(l,2,3,4)(2.5,3,4)5.7案例精选例3:编写函数,接收字符串参数,返回一个元组,其中第一个元素为大写 字母个数,第二个元素为小写字母个数。def demo(s):result=0,0for ch in s:if a=ch=,z:result 1 +=1el if k=ch=Z:result 0+=1return resultprint(demo(aaaabbbbC,)1,85.7案例精选例4:编写函数,接收包含20个整数的列表1 st和一个整数k作为参数,返回新列表。处理规则为:将列表1 st中下标k之前的元素逆序,下标k之后的元素逆序,然后将 整个列表1 st中的所有元素逆序。print(1 st)print(demo(1 stdef demo(1 st,k):x=1 st:kx.reverse()y=1 st k:y.reverse()r=x+y r.reverse()return r 1 st=list(range(1,21)1,2,3,%5,6,7,8,%10,11,12,13,14,15,,6,7,8,9,10,11,12,13,14,15,16,17,18,19,17,18,19,201,2,3,%55.7案例精选例5:编写函数,接收整数参数t,返回斐波那契数列中大于t的第一个数。def demo(t):a,b=1,1while b0 and n%2=i3 for i in range(3,int(n/2)+1):if I sPrime(i)and I sPrime(n-i)2329print(i,,+,n-i,,=,n)一一+i+i+i+7 33 4 45o O0 6 6 6o o O6 6 61A 7 414 3 3demo(60)5.7案例精选例9:编写函数,接收两个正整数作为参数,返回一个数组,其中第一 个元素为最大公约数,第二个元素为最小公倍数。def demo(m,n):if mn:m,n=n,m p=m*n while m!=0:r=n%m n=mm=rreturn(int(p/n),n)print(demo(20,30)(6010)8.6使用I DLE调试代码(p202)首先单击菜单“DebugDebugger”打开调试器窗口然后打开并运行要调试的程序切换到调试器窗口进行调试I DLE调试器窗口5.7案例精选例10:编写函数,接收一个所有元素值互不相等的整数数列X,和一个整数n,要求将 值n的元素作为支点,将列表中所有值小于n元素全部放到n前面,所有值大于n的元素 放到n后面。+练习:1.录入例5T0(pl44)并且运行该程序2.使用I DLE调试代码5.8高级话题(自学)5.8高级话题内置函数map可以将一个函数作用到一个序列或迭代器对象上。list(map(str,range(5)O,1,2,3,4 def add5(v):return v+5 list(map(add5,range(1 0)5,6,7,8,9,1 0,1 1,1 2,1 3,1 45.8高级话题内置函数reduce可以将一个接受2个参数的函数以累积的方式从左到右依 次作用到一个序列或迭代器对象的所有元素上。在python 3中,使用reduce函数需要 from functools import reduce from functools import reduce 0 seq=l,2,3,4,5,6,7,8,9 J reduce(lambda x,y:x+y,seq)345 1 def add(x,y):return x+y 1 05 reduce(add,range(1 0)reduce(add,map(str,range(1 0)01 23456 7895.8高级话题内置函数filter将一个函数作用到一个序列上,返回该序列中使得该函数 返回值为True的那些元素组成的列表、元组或字符串。seq=foo,x41 *def func(x):return x.isalnum()list(filter(func,seq)foo?,x41 seq foo,x41,?!,*x for x in seq if x.isalnum()foo?,x41 list(filter(lambda x:x.isalnum(),seq)foo?,x41 5.8高级话题生成器:包含yield语句的函数创建生成器,惰性求值,可迭代,适用于大数据处理示例:生成斐波那契数列 def f():a,b=1,1while True:yield aa,b=b,a+bt r-o afnnt 1 r 1,i rpr(ae gn aX e n耳 n e55432131X853211next_()next_()next()next()next_()next_()next_()next_()for i in f 0*print(i)if i 1 000:break7437079 314594371851 1 oo no 0011 oo no 0011 oo Qu 15.8高级话题使用dis模块可以查看函数的字节码指令 def add(n):n+=lreturn n import dis dis.dis(add)20 LOAD_FAST0(n)3 LOAD_CON ST16 I N PLACE_ADD7 STOR E_FAST0(n)31 0 L0AD_FAST1 3 R ETUR N VALUE0(n)5.8高级话题函数嵌套定义与可调用对象在Python中,函数是 可以嵌套定义的。def linear(a,b):def result(x):return a*x+breturn result taxes=1 inear(0.3,2)taxes(5)3.5 class linear:def init(self,a,b):self.a,self,b=a,bdef call(self,x):return self,a*x+self,b任何包含CaH_()方法的类的 对象都是可调用的。taxes=linear(0.3,2)taxes(5)3.55.8高级话题把列表中所有元素循环左移k位。在collections标准库的deque对象已经实现了 该功能,直接调用即可。import collections x=range(20)list(x)0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,1 9 x=collections.deque(x)xdeque(0,1,2,3,4,5,6,7,8,9,1 0,1 1,1 2,1 3,1 4,1 5,1 6,1 7,1 8,1 9)x.rotate(-3)xdeque(3,4,5,6,7,8,9,1 0,1 1,1 2,1 3,1 4,1 5,1 6,1 7,1 8,1 9,0,1,2)x=list(x)x 3,4,5,6,7,8,9,1 0,1 1,1 2,1 3,1 4,1 5,1 6,1 7,1 8,1 9,0,1,2
展开阅读全文