您好,欢迎访问三七文档
当前位置:首页 > IT计算机/网络 > AI人工智能 > python函数设计与异常(PPT61页)
Python函数设计和异常汇报人:付红玉汇报时间:2018年5月一函数设计与使用1“”Python函数将可能需要反复执行的代码封装为函数,并在需要执行该段代码功能的地方进行调用,不仅可以实现代码的复用,更重要的是可以保证代码的一致性,只需要修改该函数代码则所有调用位置均得到体现。在编写函数时,有很多原则需要参考和遵守:1、不要在同一个函数中执行太多的功能,尽量只让其完成一个高度相关且大小合适的功能,以提高模块的内聚性。2、尽量减少不同函数之间的隐式耦合,例如减少全局变量的使用,使得函数之间仅通过调用和参数传递来显式体现其相互关系。2函数定义函数定义语法:def函数名([参数列表]):'''注释'''函数体函数形参不需要声明类型,也不需要指定函数返回值类型即使该函数不需要接收任何参数,也必须保留一对空的圆括号括号后面的冒号必不可少函数体相对于def关键字必须保持一定的空格缩进Python允许嵌套定义函数注意事项√√√√√3函数定义格式生成斐波那契数列的函数定义和调用:调用函数1000是实参n是形参deffib(n):a,b=1,1whilean:print(a,end='')a,b=b,a+bprint()fib(1000)定义头函数体4函数的注释在定义函数时,开头部分的注释并不是必需的,但如果为函数的定义加上注释的话,可以为用户提供友好的提示.5函数对象的增加、删除Python是一种高级动态编程语言,变量类型是随时可以改变的。Python中的函数和自定义对象的成员也是可以随时发生改变的,可以为函数和自定义对象动态增加新成员。deffunc():print(func.x)#查看func的成员func()#现在函数func还没有成员x,出错AttributeError:'function'objecthasnoattribute'x‘func.x=3#动态为函数增加新成员func()3delfunc.x#删除成员func()#删除之后不可访问AttributeError:'function'objecthasnoattribute'x‘6函数的递归调用函数的递归调用是函数调用的一种情况,函数调用自己,自己再调用自己,自己再调用自己,…,当某个条件得到满足的时候,就不再调用了,然后再一层一层地返回知道该函数第一次调用的位置需要用栈来存储该函数离开的位置,栈比较小,如果递归调用很深,则导致栈崩溃7尾递归尾递归是指:在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。8递归实现n的阶乘:deffact(n):ifn==1:return1returnn*fact(n-1)deffact(n):returnfact_iter(n,1)deffact_iter(num,product):ifnum==1:returnproductreturnfact_iter(num-1,num*product)改成尾递归returnfact_iter(num-1,num*product)仅返回递归函数本身num-1和num*product在函数调用前就会被计算,不影响函数调用遗憾的是:大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出010203在Python中,定义函数时不需要声明函数的返回值类型,而是使用return语句结束函数的执行的同时返回任意类型的值,函数返回值类型与return语句返回表达式的类型一致。如果函数没有return语句或者执行了不返回任何值的return语句,Python将认为该函数以returnNone结束,即返回空值函数基本语法9不论return语句出现在函数的什么位置,一旦得到执行将直接结束函数的执行。函数参数不得不说的几件事(一)1)在定义函数时,对参数个数并没有限制,如果有多个形参,则需要使用逗号进行分隔.下面的函数用来接收2个参数,并输出其中的最大值:defprintMax(a,b):ifab:pirnt(a,'isthemax')else:print(b,'isthemax')2)对于绝大多数情况下,在函数内部直接修改形参的值不会影响实参:defaddOne(a):print(a)#输出原变量a的值a+=1#这条语句会得到一个新的变量aprint(a)a=3addOne(a)34a310函数参数不得不说的几件事(二)在有些情况下,可以通过特殊的方式在函数内部修改实参的值。defmodify(v):#修改列表元素值v[0]=v[0]+1a=[2]modify(a)a[3]defmodify(v,item):#为列表增加元素v.append(item)a=[2]modify(a,3)a[2,3]defmodify(d):#修改字典元素值或为字典增加元素d['age']=38a={'name':'Dong','age':37,'sex':'Male'}a{'age':37,'name':'Dong','sex':'Male'}modify(a)a{'age':38,'name':'Dong','sex':'Male'}11函数参数不得不说的几件事(三)默认值参数在调用带有默认值参数的函数时,可以不用为设置了默认值的形参进行传值,此时函数将会直接使用函数定义时设置的默认值,也可以通过显式赋值来替换其默认值。def函数名(……,形参名=默认值):函数体可以使用“函数名.__defaults__”随时查看函数所有默认值参数的当前值,其返回值为一个元组,其中的元素依次表示每个默认值参数的当前值。defsay(message,times=1):print((message+'')*times)say.__defaults__(1,)注意:函数参数的默认值是在定义函数时确定的12函数参数不得不说的几件事(四)(2)关键参数通过关键参数可以按参数名字传递值,实参顺序可以和形参顺序不一致,但不影响参数值的传递结果,避免了用户需要牢记参数位置和顺序的麻烦,使得函数的调用和参数传递更加灵活方便。defdemo(a,b,c=5):print(a,b,c)demo(c=8,a=9,b=0)90813函数参数不得不说的几件事(五)(3)可变长度参数可变长度参数在定义函数时主要有两种形式:*parameter和**parameter,前者用来接收任意多个实参并将其放在一个元组中,后者接收类似于关键参数一样显式赋值形式的多个实参并将其放入字典中。第一种形式可变长度参数的用法,无论调用该函数时传递了多少实参,一律将其放入元组中:defdemo(*p):print(p)demo(1,2,3,4,5,6,7)(1,2,3,4,5,6,7)第二种形式可变长度参数的用法:defdemo(**p):foriteminp.items():print(item)demo(x=1,y=2,z=3)('y',2)('x',1)('z',3)14函数参数不得不说的几件事(六)传递参数时的序列解包defdemo(a,b,c):print(a+b+c)seq=[1,2,3]demo(*seq)6tup=(1,2,3)demo(*tup)6dic={1:'a',2:'b',3:'c'}demo(*dic)6Set={1,2,3}demo(*Set)6demo(*dic.values())abc15Key作为实参函数参数不得不说的几件事(七)注意:调用函数时如果对实参使用一个星号*进行序列解包,这么这些解包后的实参将会被当做普通位置参数对待,并且会在关键参数和使用两个星号**进行序列解包的参数之前进行处理。defdemo(a,b,c):#定义函数print(a,b,c)demo(a=1,*(2,3))#序列解包相当于位置参数,优先处理Traceback(mostrecentcalllast):Filepyshell#26,line1,inmoduledemo(a=1,*(2,3))TypeError:demo()gotmultiplevaluesforargument'a'demo(c=1,*(2,3))231demo(**{'a':1,'b':2},*(3,))#序列解包不能在关键参数解包之后SyntaxError:iterableargumentunpackingfollowskeywordargumentunpackingdemo(*(3,),**{'c':1,'b':2})32116参数检查调用函数时,如果参数个数不对,Python解释器会自动检查出来,并抛出TypeError:17defmy_abs(x):ifx=0:returnxelse:return-xmy_abs(1,2)Traceback(mostrecentcalllast):Filestdin,line1,inmoduleTypeError:my_abs()takes1positionalargumentbut2weregiven如果参数类型不对,Python解释器就无法帮我们检查。看一下my_abs和内置函数abs的差别:my_abs('A')Traceback(mostrecentcalllast):Filestdin,line1,inmoduleFilestdin,line2,inmy_absTypeError:unorderabletypes:str()=int()abs('A')Traceback(mostrecentcalllast):Filestdin,line1,inmoduleTypeError:badoperandtypeforabs():'str'参数检查我们修改一下my_abs的定义,对参数类型做检查,只允许整数和浮点数类型的参数。数据类型检查可以用内置函数isinstance()实现:18defmy_abs(x):ifnotisinstance(x,(int,float)):raiseTypeError('badoperandtype')ifx=0:returnxelse:return-xmy_abs('A')Traceback(mostrecentcalllast):Filestdin,line1,inmoduleFilestdin,line3,inmy_absTypeError:badoperandtype变量的作用域1、变量起作用的代码范围称为变量的作用域,不同作用域内变量名可以相同,互不影响2、在函数内部定义的普通变量只在函数内部起作用,称为局部变量。当函数执行结束后,局部变量自动删除,不再可以使用3、局部变量的引用比全局变量速度快,应优先考虑使用1、一个变量已在函数外定义,如果在函数内需要为这个变量赋值,并要将这个赋值结果反映到函数外,可以在函数内使用global将其声明为全局变量。2、如果一个变量在函数外没有定义,在函数内部也可以直接将一个变量定义为全局变量,该函数执行后,将增加一个新的全局变量。全局变量可以通过关键字global来定义。这分为两种情况:19defdemo():globalxx=3y=4print(x,y)x=5demo()34x3yNameError:name'y'isnotdefineddelxxNameError:name'x'isnotdefineddemo()34x3yNameError:name'y'isno
本文标题:python函数设计与异常(PPT61页)
链接地址:https://www.777doc.com/doc-25990 .html