版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Python5函数设计与使用Python5函数设计与使用Python5函数设计与使用Python5函数设计与使用Python5函数设计与使用1函数在实际开发中,有许多操作时完全相同或非常相似的,仅仅是要处理的数据不同,为此需要实现代码复用。函数:可能需要反复执行的代码封装为函数,并在需要该段代码功能的地方调用。可以实现代码的复用更重要的是可以保证代码的一致性,只需要修改该函数代码则所有调用均受到影响Python提供了许多常用的内置函数如len(),sum()等,也可以自定义函数。另一种代码复用方式:定义面向对象程序设计中的类函数在实际开发中,有许多操作时完全相同或非常相似的,仅仅是要25.1函数定义与调用5.1函数定义与调用35.1函数定义与调用创建或定义函数要使用def关键字函数定义(声明)格式:
def函数名([形参列表]):
'''可选的注释'''
函数体函数调用:
函数名([实参列表])注意:函数名命名规则建议为全小写字母,可以用下划线增加阅读性,如my_func形参列表用()括起来,一个函数可以没有形参(parameter),表示不需要接收任何参数,但是括弧必须要有括号后面的冒号必不可少,表示接下来是函数体#!/usr/local/bin/python3#-*-coding:utf-8-*-"""functiondemo"""
def
fib(n):
'''acceptanintegern.returnthenumberslessthanninFibonaccisequence.'''a,b=
1,
1
whilea<n:
print(a,end='')a,b=b,a+b
print()
def
test_fib(
):n=int(input('请输入整数n:'))fib(n)5.1函数定义与调用创建或定义函数要使用def关键字#!/45.1函数定义与调用创建或定义函数要使用def关键字函数定义(声明)格式:
def函数名([形参列表]):
'''注释'''
函数体函数调用:
函数名([实参列表])def
fib(n):
'''acceptanintegern.returnthenumberslessthanninFibonaccisequence.'''a,b=
1,
1
whilea<n:
print(a,end='')a,b=b,a+b
print()def
cubic(n):
returnn**3
函数体一般包括多行,相对于def关键字必须保持一定的空格缩进,是函数执行的代码块如果函数体比较简单时,也可以与def在同一行:pass语句为空语句,经常用在定义一个空函数,以后再扩充函数可以返回值,也可以不返回。如果函数体中包含return语句,则执行到那里时从函数中返回(同时返回return语句中相应表达式的值,如果未指定则为None),后面的代码不再执行如果执行到函数结束也无return语句,则等价于returnNone函数调用时,根据需要,可指定实际传入的参数值,同时获取返回值5.1函数定义与调用创建或定义函数要使用def关键字def55.1函数定义与调用定义函数(及模块)时,开头部分的注释并不是必需的,但是如果为函数的定义加上这段注释的话,可以为用户提供友好的提示和使用帮助。该字符串保存在函数(及模块)对象的__doc__属性中,称为docstringhelp(fib)可以查看相应的__doc__属性IDE界面会给出相应的calltip#!/usr/local/bin/python3#-*-coding:utf-8-*-"""functiondemo"""
def
fib(n):
'''acceptanintegern.returnthenumberslessthanninFibonaccisequence.'''a,b=
1,
1
whilea<n:
print(a,end='')a,b=b,a+b
print()
def
test_fib(
):n=int(input('请输入整数n:'))fib(n)5.1函数定义与调用定义函数(及模块)时,开头部分的注释并65.2形参与实参5.2形参与实参75.2形参与实参函数定义(声明)格式:
def函数名([形参列表]):
'''注释'''
函数体函数调用:
函数名([实参列表])>>>deffib(n):
'''acceptanintegern.returnthenumberslessthanninFibonaccisequence.'''a,b=1,1whilea<n:print(a,end='')a,b=b,a+bprint()>>>fib(1000)#函数调用1123581321345589144233377610987形参(parameter)实参(argument)5.2形参与实参函数定义(声明)格式:>>>deffi85.2形参与实参定义函数时,对参数个数没有限制,如有多个形参,则需要使用逗号进行分隔。如:编写函数,接受两个整数,并输出其中最大数。>>>defprintMax(a,b):
ifa>b:print(a,'isthemax')
else:print(b,'isthemax')>>>printMax(3,4)4isthemax注意:这个程序如果输入的参数不支持比较运算,会出错。5.2形参与实参定义函数时,对参数个数没有限制,如有多个形95.2形参与实参为了避免sideeffect,函数中的形参(变量)的使用范围为函数体(作用域部分会详细介绍)函数调用时向其传递实参,python采用赋值传递(passbyassignment)的策略与其它高级语言的passbyvalue以及passbyreference不同形参变量=实参变量,即形参变量与实参变量指向同一个对象绝大多数情况下,在函数内部直接修改形参的值不会影响实参对于不可变对象,显然如此对于可变对象,如果不是采用in-place(原地)方法来改变该可变对象的值时,也不会影响>>>def
addOne(a): print(a) a+=1 print(a)>>>a=3>>>addOne(a)34>>>a35.2形参与实参为了避免sideeffect,函数中的形105.2形参与实参可变对象的原地操作会影响函数外部实参的值,许多时候会要利用该特性>>>defmodify(v):#修改列表元素值
v[0]=v[0]+1
>>>a=[2]>>>modify(a)>>>a[3]注意:如果传递给函数的是Python可变序列,并且在函数内部使用下标或其他方式为可变序列增加、删除元素或修改元素值时,可以使得实参得到相应的修改。>>>defmodify(v,item):#为列表增加元素
v.append(item)
>>>a=[2]>>>modify(a,3)>>>a[2,3]>>>defmodify(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'}5.2形参与实参可变对象的原地操作会影响函数外部实参的值,115.3参数类型5.3参数类型125.3参数类型在Python中,函数参数有很多种:普通参数默认值参数关键参数可变长度参数等等。Python函数的定义非常灵活,在定义函数时不需要指定参数的类型,形参的类型完全由调用者传递的实参类型以及Python解释器的理解和推断来决定,类似于重载和泛型(polymorphism);函数编写如果有问题,只有在调用时才能被发现,传递某些参数时执行正确,而传递另一些类型的参数时则出现错误。5.3参数类型在Python中,函数参数有很多种:135.3.1默认值参数Python在定义函数时,支持默认值参数,即可为形参设置默认值。def函数名(……,形参名=默认值)函数体仅仅包含形参名的参数称为位置(positional)参数,根据其出现的位置顺序来逐个匹配相应的实参调用带有默认值参数的函数时,可以不对默认值参数进行赋值,也可以赋值,具有较大的灵活性。使用“函数名.__defaults__”以元组的形式查看函数所有默认值参数的当前值。>>>defsay(message,times=1): print(message*times)
>>>say('hello')#不为默认值参数传值hello>>>say('hello',3)#使用调用者显示传递的值hellohellohello>>>say('hi',7)#使用调用者显示传递的值hihihihihihihi>>>say.__defaults__(1,)5.3.1默认值参数Python在定义函数时,支持默认值参数145.3.1默认值参数(defaultsparameter)函数定义时最前面是位置参数,然后是默认值参数即默认值参数右边不能再有位置参数。为什么这样设计?函数调用时默认值参数可能并没有包含在实参中!5.3.1默认值参数(defaultsparameter)155.3.1默认值参数例:使用指定分隔符将列表中所有字符串元素连接成一个字符串,默认空格。>>>defJoin(List,sep=None): return(sepor'').join(List)>>>aList=['a','b','c']>>>Join(aList)'abc‘>>>Join(aList,',')'a,b,c'5.3.1默认值参数例:使用指定分隔符将列表中所有字符串元素165.3.1默认值参数在函数定义时,计算默认值得到一个tuple,然后保存在func.__defaults__函数调用时如何确定默认值参数的值?如果实参中给出了相应的值,则该形参指向实参所引用的对象如果实参没有传递值,则该形参变量赋予默认值,而默认值保存在func.__defaults__如果默认值参数的默认值为可变对象,且前面调用该函数时原地修改了该对象,保存在__defaults__元组中的默认值也会被修改这种特性可能导致很难发现的逻辑错误。也可能是故意这样来设计在函数的多次调用间保存状态信息5.3.1默认值参数在函数定义时,计算默认值得到一个tupl175.3.1默认值参数>>>defdemo(newitem,old_list=[]):old_list.append(newitem)returnold_list>>>print(demo('5',[1,2,3,4]))#right[1,2,3,4,'5']>>>print(demo('aaa',['a','b']))#right['a','b','aaa']>>>print(demo('a'))#right['a']>>>print(demo('b'))['a','b']>>>print(demo.__defaults__)(['a','b'],)注意:多次调用函数并且不为默认值参数传递值时,默认值参数值在第一次调用时被更改,可以使用函数名.__defaults__查看默认参数的当前值如何修改?5.3.1默认值参数>>>defdemo(newitem185.3.1默认值参数修改程序如下:defdemo(newitem,old_list=None):ifold_listisNone:old_list=[]old_list.append(newitem)returnold_listprint(demo('5',[1,2,3,4]))#rightprint(demo('aaa',['a','b']))#rightprint(demo('a'))#rightprint(demo.__defaults__)print(demo('b'))+运行该程序,看看和前面的有什么不同?缺省值参数的缺省值避免采用可变对象,或者采用可变对象但是函数体不要进行原地操作。除非故意设计以利用可变对象的这一特征5.3.1默认值参数修改程序如下:defdemo(newi195.3.2关键字参数(keywordargument)关键字参数主要指实参,即调用函数时的参数传递方式。通过关键字参数可以按参数名字传递值,实参顺序可以和形参顺序不一致,但不影响传递结果,避免了用户需要牢记位置参数顺序的麻烦。在函数定义中有多个缺省值参数时通过关键字参数来明确传递哪些参数,哪些采用缺省值注意关键字参数与函数定义时的缺省值参数的区别,虽然两者形式一致,但两者之间并不等同调用时可以使用位置参数和关键字来传递参数,但是与函数定义时类似,关键字参数右边不能有位置参数
>>>defdemo(a,b,c=5): print(a,b,c)>>>demo(3,7)375>>>demo(a=7,b=3,c=6)736>>>demo(c=8,a=9,b=0)908deffunc(a,b,c=5,d=6):print(a,b,c,d)func(1,2,7)func(1,2,5,8)func(b=1,a=2,c=7)func(1,2,d=8)func(1,b=2,d=8)5.3.2关键字参数(keywordargument)关键205.3.3可变长度参数(variable-lengthparameters)可变长度参数在定义函数时主要有两种形式:*parameter:将那些尚没有匹配形参的位置实参组合成一个元组赋值给可变长度位置参数。**parameter:将那些尚没有匹配形参的关键字实参组合成一个dict赋值给该参数如果存在,*name形式的参数应该出现在缺省值参数之后如果存在,**name形式的参数应该出现在最后每种类型的可变长度参数只能出现一次>>>defdemo(*p): print(p)>>>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)*parameter无论调用该函数时传递了多少实参,没有匹配的位置参数一律将其放在元组中。5.3.3可变长度参数(variable-lengthp215.3.3可变长度参数(variable-lengthparameters)可变长度参数在定义函数时主要有两种形式:*parameter:收集没有匹配的位置实参放在一个元组中**parameter,收集没有匹配的关键字实参放在一个字典中。>>>defdemo(*p): print(p)>>>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)(1)*parameter无论调用该函数时传递了多少实参,一律将其放在元组中。>>>defdemo(**p): foriteminp.items(): print(item)
>>>demo(x=1,y=2,z=3)('z',3)('y',2)('x',1)(2
)**parameter调用该函数时自动将接收的关键字参数转换为字典。5.3.3可变长度参数(variable-lengthpa22仅允许关键字传递的形参(keyword-onlyparameter)补充Python3还引入了keyword-only形参,即这些参数只能通过关键字参数的形式来传递keyword-only参数出现在可变长度的位置参数之后如果没有可变长度位置参数,则添加一个*keyword-only参数也可以指定缺省值,即支持name或者name=default方式调用时必须采取关键字参数传递,或者不传递表示采用缺省值def
kwonly(a,
*b,c,d=5):
return
(a,b,c,d)
def
kwonly2(a,b,*,c,d=5):
return
(a,b,c,d)
print(kwonly(1,
2,c=3))print(kwonly2(1,
2,c=3,d=4))仅允许关键字传递的形参(keyword-onlyparam23形参与实参之间的匹配函数定义中的形参顺序位置参数
缺省值参数
可变长度位置参数
仅允许关键字传递参数
可变长度字典参数函数调用中的实参顺序:位置参数
关键字参数函数调用时,根据传递的实参按照以下规则匹配形参:首先按照位置匹配形参中的位置参数和缺省值参数接下来根据关键字参数的名字匹配形参中的各个参数剩下的位置参数组成tuple赋值给可变长度位置参数剩下的关键字参数组成dict赋值给可变长度字典参数函数定义中尚未匹配的参数设置为缺省值如果仍然有尚未匹配的形参和实参则报错每个参数只能匹配一次形参与实参之间的匹配函数定义中的形参顺序245.3.3可变长度参数(教材上例子)几种不同类型的参数可以混合使用不建议这样做,易导致代码混乱而严重降低可读性,可能导致查错非常困难>>>deffunc_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='1',yy='2',zz=3)123(4,5,6,7,8,9){'zz':3,'xx':'1','yy':'2'}>>>func_4(1,2,3,4,5,6,7,xx='1',yy='2',zz=3)123(4,5,6,7){'zz':3,'xx':'1','yy':'2'}5.3.3可变长度参数(教材上例子)几种不同类型的参数可以混25例子def
_print(*args,sep='',end='\n',file=sys.stdout,flush=False):line=
[]
forvalueinargs:line.append(format(value))file.write(sep.join(line))file.write(end)
ifflush:file.flush()def
_trace(func,*args,**kwargs):
ifhasattr(func,'calls'):func.calls+=
1
else:func.calls=
1
ifkwargs:
print('[%d]callingfunction:%s(%s,%s)'%
(func.calls,func.__name__,
','.join(map(str,args)),
','.join([k+'='+str(v)
fork,vinkwargs.items()])))
else:
print('[%d]callingfunction:%s(%s)'%
(func.calls,func.__name__,
','.join(map(str,args))))
returnfunc(*args,**kwargs)_print函数实现print类似的功能_trace:跟踪函数的调用,利用函数对象的属性来保存函数调用的状态信息。注意内置函数不支持用户自定义的属性+思考:你还知道有什么办法来保存函数调用的状态信息吗?例子def_print(*args,sep='',en265.3.4参数传递的序列解包为含有多个变量的函数传递参数时,可以使用Python列表、元组、集合、字典以及其他可迭代对象作为实参,并在实参名称前加一个星号*,Python解释器将自动进行解包。等价于传递多个参数,每个参数为迭代对象的每个元素(对于字典而言为每个key)**表示对于字典对象进行序列解包等价于传递多个关键字参数,关键字的变量名为字典对象dictobj的key,而值为dictobj[key]注意序列解包与函数定义时的可变长参数的区别。>>>defdemo(a,b,c): print(a+b+c) >>>seq=[1,2,3]>>>demo(*seq)6>>>tup=(1,2,3)>>>demo(*tup)6>>>dic={1:'a',2:'b',3:'c'}>>>demo(*dic)6>>>set={1,2,3}>>>demo(*set)6>>>demo(*dic.values())abc>>>dic2={'a':1,'b':2,'c':3}
>>>demo(**dic2)65.3.4参数传递的序列解包为含有多个变量的函数传递参数时27例子def
_trace(func,*args,**kwargs):
ifhasattr(func,'calls'):func.calls+=
1
else:func.calls=
1
ifkwargs:
print('[%d]callingfunction:%s(%s,%s)'%
(func.calls,func.__name__,
','.join(map(str,args)),
','.join([k+'='+str(v)
fork,vinkwargs.items()])))
else:
print('[%d]callingfunction:%s(%s)'%
(func.calls,func.__name__,
','.join(map(str,args))))
returnfunc(*args,**kwargs)例子def_trace(func,*args,**kwar285.4return语句5.4return语句295.4return语句return语句用于从一个函数中返回并结束函数的执行,同时还可以通过其从函数中返回一个值。无论return语句出现在函数的什么位置,一旦得到执行将直接结束函数的执行。函数的返回值类型由return语句返回值的类型来决定如果函数没有return语句或者没有执行return语句,执行了不带任何值的return语句,则函数都默认为返回空值None。>>>defmaximum(x,y): ifx>y: returnx else: returny>>>theMax=maximum(3,4)>>>print(theMax)45.4return语句return语句用于从一个函数中返回305.4return语句在调用内置数据类型的方法时,一定要注意该方法有没有返回值。print([1,2,3,4,9,5,7].sort())可能不是想要的结果:sort方法为原地排序,返回None>>>defmaximum(x,y): ifx>y: returnx else: returny>>>theMax=maximum(3,4)>>>print(theMax)4>>>defmaximum(x,y): ifx>y: print(x) else: print(y)>>>theMax=maximum(3,4)4>>>print(theMax)None(1)具有返回值(2)
没有返回值。5.4return语句在调用内置数据类型的方法时,一定要注318.6
使用IDLE调试代码(p202)首先单击菜单“Debug””Debugger”打开调试器窗口然后打开并运行要调试的程序切换到调试器窗口进行调试IDEL调试器窗口Go:继续执行Step:按顺序执行代码Over:按顺序执行代码,如果为函数,则不进入函数体内Out:执行代码直到跳出当前函数体在源代码.py文件中鼠标右键弹出上下文菜单后可以设置和清除当前行的断点
8.6使用IDLE调试代码(p202)首先单击菜单“Deb325.5变量作用域5.5变量作用域335.5变量作用域(scope)变量保存的是对象的引用:变量起作用的范围称为变量作用域。对象没有所谓作用域的概念,但是要引用对象,必须要通过变量一个变量在函数外部定义和在函数内部定义,其作用域是不同的:只有定义(赋值)、global和nonlocal才会建立或者改变变量的作用域局部变量:一般而言,在函数内部定义(包括参数)的变量,有效范围为函数体全局变量:在模块内定义且不在函数内定义的变量,有效范围为定义的模块局部变量的引用比全局变量速度快。全局变量增加了不同函数之间的隐式耦合度。5.5变量作用域(scope)变量保存的是对象的引用:345.5.1局部变量局部变量在函数内定义,只在该函数内起作用函数的形参属于局部变量函数结束时,无法再访问局部变量被自动删除。def
local(a=0):x=
3y=
4
print(a,x,y)#print(X)
X=
88
#globallocal(2)print(x)234Traceback(mostrecentcalllast):print(x)NameError:name'x'isnotdefined5.5.1局部变量局部变量在函数内定义,只在该函数内起作用355.5.2全局变量全局变量:其作用域为全局的,能够同时作用于函数内外。deffunc1(a=0):x=
3y=
4
print(a,x,y)
print(X)
X=
88
#globalprint(X)func1(2)8823488def
local(a=0):x=
3y=
4
print(a,x,y)#print(X)
X=
88
#globallocal(2)print(x)234Traceback(mostrecentcalllast):print(x)NameError:name'x'isnotdefined变量绑定:决定变量所指向的对象latebinding:函数中的变量在调用时才会绑定5.5.2全局变量全局变量:其作用域为全局的,能够同时作用36函数作用域可以在任何地方(选择、循环、函数内部)定义函数,只要该处支持语句选择和循环结构不会改变变量的作用域:在退出循环之后仍然有效列表解析式中引入的变量是局部变量,退出之后不再有效latebinding:函数中的全局变量在调用时才会绑定functions=
[]fornin
[1,
2,
3]:
def
func(x):
returnn*xfunctions.append(func)
#期待输出[2,4,6],但是输出[6,6,6]print([function(2)
forfunctioninfunctions])
functions=
[]fornin
[1,
2,
3]:
def
func(x,n=n):
returnn*xfunctions.append(func)
print([function(2)
forfunctioninfunctions])
函数作用域可以在任何地方(选择、循环、函数内部)定义函数,只37变量的作用域搜索在访问变量(注意不是赋值)时,怎么找到具体是哪个作用域内的变量?Local:函数内部赋值的变量,且没有通过global/nonlocal声明过
Enclosing:外层函数内部赋值的变量,从最里层往外层搜索
Global(模块):在函数外部定义的变量或者在函数体内通过global声明过Builtin(python):在python环境的内置模块built-in中定义的变量LEGB规则:按照顺序搜索相应的作用域,直到找到匹配为止LocalEnclosingGlobalBuiltinglobalx:改变x的作用域为全局变量nonlocalx:表示x不是局部变量,而是外层函数中定义的变量,跳过local作用域从里到外往外层函数(但不会到函数外)搜索变量的作用域搜索在访问变量(注意不是赋值)时,怎么找到具体是38赋值改变作用域注意:global/nonlocal会跳过局部作用域,改变其作用域分别为全局范围和外层的某个函数范围。赋值会改变变量的作用域,而赋值发生的地方决定了其所在的作用域def
func1():
print(X)
def
func2():
print(X)X=X+
1
print(X)X=
88func1()print()func2()print()88Traceback(mostrecentcalllast):print(X)UnboundLocalError:localvariable'X'referencedbeforeassignmentX在函数体内赋值,作用域为Local赋值改变作用域注意:deffunc1():88X在函数体内39赋值改变作用域内层的(局部)变量会隐藏更外层同名的(全局)变量def
func1():
print(X)
def
func2():
print(X)X=X+
1
print(X)def
func2_():
print(X)
Y=X+
1
print(Y)X=88func2_()8889def
func3():X=
1
print(X)X=88func3()88UnboundLocalError:localvariable'X'1def
func3_():X=
1
print(X)
importsys
print(sys.modules[__name__].X)
88可通过模块对象来访问全局变量赋值改变作用域内层的(局部)变量会隐藏更外层同名的(全局)变40global改变作用域globalx:表示x为全局变量,当函数体要改变全局变量的值时使用def
func1():
print(X)
def
func2():
print(X)X=X+
1
print(X)def
func2_():
print(X)
Y=X+
1
print(Y)X=88func2_()print(X)88898888UnboundLocalError:localvariable'X'def
func4():
globalX
print(X)
#globalXX=X+
1
print(X)
func4(
)print(X)
888989global改变作用域globalx:表示x为全局变量,415.8高级话题(6)嵌套函数(补充)在函数体内再定义新的函数Python中函数也是对象def
linear(a,b):
def
result(x):
returna*x+b
returnresult
func_1_1=linear(1,
1)func_2_1=linear(2,
1)print('f(x)=x+1,f(10)=',func_1_1(10))print('f(x)=2x+1,f(10)=',func_2_1(10))自由变量:在函数体内未赋值但是使用的变量在result函数定义时,a和b为自由变量按照LEGB规则,自由变量继续在外层函数中由里到外寻找。每次调用linear返回一个新的函数对象func,返回的函数对象不再依赖于外层函数linear(实际上已经返回退出了)外层函数return时进行非全局的自由变量的绑定保存在func.__closure__中含有自由变量的代码块称为闭包(closure)5.8高级话题(6)嵌套函数(补充)在函数体内再定义新的42嵌套函数的latebinding不是在定义函数时绑定,而是在定义函数的函数体中返回时绑定非全局的自由变量在函数调用时绑定全局变量
def
makeActs():funcs=
[]
foriinrange(3):j=
[i]
print(hex(id(j)))
def
func(n):
print(n*j[0])
print(hex(id(j)))funcs.append(func)
returnfuncs
acts=makeActs()[act(10)
foractinacts]0x1148da00x113d6980x11478f0200x11478f0200x11478f0200x11478f0期待输出为:0*n,n,*2n(n=10),即0,10,20实际输出:20,20,20可以看到自由变量j都指向同一个对象
与global语句类似,如果在内层函数要对于外层的自由变量赋值,需要使用nonlocal语句表示函数体赋值不会变为局部变量,而是外层函数的自由变量嵌套函数的latebinding不是在定义函数时绑定,而是43嵌套函数的latebindingdef
makeActs2():funcs=
[]
foriinrange(3):j=
[i]
print(hex(id(j)))
def
func(n,
j=j):
print(n*j[0])
print(hex(id(j)))funcs.append(func)
returnfuncs
acts2=makeActs2()[act(10)
foractinacts2]
def
makeActs():funcs=
[]
foriinrange(3):j=
[i]
print(hex(id(j)))
def
func(n):
print(n*j[0])
print(hex(id(j)))funcs.append(func)
returnfuncs
acts=makeActs()[act(10)
foractinacts]0x11334400x113d0800x114237800x1133440100x113d080200x1142378嵌套函数的latebindingdefmakeActs2445.8高级话题:可调用对象函数可以调用,实际上函数通过classfunction来实现自己定义的类如果实现了__call__()方法,则也是可调用对象class
linear2:
def
__init__(self,a,b):self.a,self.b=a,b
def
__call__(self,x):
returnself.a*x+self.b
taxes=linear2(0.3,2)print(taxes(5))
#3.5def
linear(a,b):
def
result(x):
returna*x+b
returnresult
dir(linear)dir(linear2)5.8高级话题:可调用对象函数可以调用,实际上函数通过c455.5.2全局变量(教材上的例子)全局变量:其作用域为全局的,能够同时作用于函数内外。>>>defdemo(): globalx x=3 y=4 print(x,y)>>>x=5>>>demo()34>>>x3>>>yTraceback(mostrecentcalllast):File"<pyshell#83>",line1,in<module>yNameError:name'y'isnotdefined>>>delx>>>xTraceback(mostrecentcalllast):File"<pyshell#85>",line1,in<module>xNameError:name'x'isnotdefined一个变量已在函数外定义,如果在函数内需要为这个变量赋值,并要将这个赋值结果反映到函数外,可以在函数内用global声明这个变量,将其映射到全局作用域。5.5.2全局变量(教材上的例子)全局变量:其作用域为全局465.5.2全局变量(教材上的例子)全局变量:其作用域为全局的,能够同时作用于函数内外>>>defdemo(): globalx x=3 y=4 print(x,y)>>>demo()34>>>x3>>>yTraceback(mostrecentcalllast):File"<pyshell#98>",line1,in<module>yNameError:name'y'isnotdefined在函数内部直接将一个变量声明为全局变量,在函数外没有声明,在调用这个函数之后,将增加为新的全局变量。5.5.2全局变量(教材上的例子)全局变量:其作用域为全局475.5.2全局变量示例示例pi=3.141592653589793e=2.718281828459045defmy_func():globalpipi=3.14print('globalpi=',pi)e=2.718print('locale=',e)print('modulepi=',pi)print('modulee=',e)my_func()print('modulepi=',pi)print('modulee=',e)5.5.2全局变量示例示例pi=3.14159265358485.6lambda表达式(自学)5.6lambda表达式(自学)495.6lambda表达式lambda表达式用来定义一个仅仅包含一行代码的匿名函数,即没有函数名字,函数体只可以包含一个表达式,且该表达式的计算结果为函数的返回值。不允许包含其他复杂的语句,只能是表达式,但是注意函数调用也是表达式,因此可以调用print、map、list等lambda表达式也是函数的一种,因此也遵循前面介绍过的函数的参数定义和传递、函数的作用域所使用的规则含有默认参数,调用时使用关键参数f=lambdax,y,z:x+y+zprint
(f(1,2,3))
def
f(x,y,z):
returnx+y+zg=lambdax,y=2,z=3:x+y+zprint
(g(2,z=4,y=5))print
(g(2,z=4))
1185.6lambda表达式lambda表达式用来定义一个仅仅505.6lambda表达式lambda表达式是匿名函数,避免了可能的名字冲突可以用作CodeJumpTable:代码跳转表可以用于那些参数为函数对象的函数,比如map、reduce、filtered、sorted等key='f1'
D='f1':
(lambda:
2
+
2),'f2':
(lambda:
2
*
4),'f3':
(lambda:
2
**
6)}
print(D[key]())
L=
[lambdax:x**
2,
lambdax:x**
3,
lambdax:x**
4]
forfinL:
print(f(2))print(L[0](3))
5.6lambda表达式lambda表达式是匿名函数,避免515.6lambda表达式>>>L=[1,2,3,4,5]>>>print(map((lambdax:x+10),L))[11,12,13,14,15]>>>L[1,2,3,4,5]>>>defdemo(n): returnn*n>>>demo(5)25>>>a_list=[1,2,3,4,5]>>>list(map(lambdax:demo(x),a_list))[1,4,9,16,25]lambda表达式不允许包含其他复杂的语句,但在表达式中可以调用其他函数。没有名字的lambda表达式没有名字的,使用函数调用的lambda表达式5.6lambda表达式>>>L=[1,2,3,4,5]525.6lambda表达式>>>data=range(20)>>>print(data)[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]>>>importrandom>>>random.shuffle(data)>>>print(data)[4,3,11,13,12,15,9,2,10,6,19,18,14,8,0,7,5,17,1,16]>>>data.sort(key=lambdax:x)>>>print(data)[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]>>>data.sort(key=lambdax:len(str(x)))>>>print(data)[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]>>>data.sort(key=lambdax:len(str(x)),reverse=True)>>>print(data)[10,11,12,13,14,15,16,17,18,19,0,1,2,3,4,5,6,7,8,9]lambda表达式其他示例5.6lambda表达式>>>data=range(20535.7案例精选5.7案例精选545.7案例精选:递归函数(补充)递归函数:指的是在函数体内直接或者间接调用本函数实现起来非常方便,但应注意递归调用不要一直进行下去,没有终止递归调用的深度是受到限制的效率较低,如果有可能通过循环实现def
factorialRecur(n):
#阶乘,通过递归实现
ifn==
1:
return
1
else:
returnn*factorialRecur(n-
1)importsysprint(sys.getrecursionlimit())
#1000old=sys.getrecursionlimit()sys.setrecursionlimit(50)print(factorialRecur(45))sys.setrecursionlimit(old)"C:\Users\dlmao\PycharmProjects\pythonClass\function.py",line540,infactorialRecurifn==1:RecursionError:maximumrecursiondepthexceededincomparisondef
factorial(n):
#阶乘,通过loop实现result=n
foriinrange(1,n):result*=i
returnresult5.7案例精选:递归函数(补充)递归函数:指的是在函数体555.7案例精选例1:编写函数计算圆的面积。frommathimportpiasPI#importtypes
def
CircleArea(r):
ifisinstance(r,int)
orisinstance(r,float):
#确保接收的参数为数值
returnPI*r*r
else:
print('Youmustgivemeanintegerorfloatasradius.')
print(CircleArea(3))28.2743338823081385.7案例精选例1:编写函数计算圆的面积。frommat565.7案例精选例2:编写函数,接收任意多个实数,返回一个元组,其中第一个元素为所有参数的平均值,其他元素为所有参数中大于平均值的实数。def
demo2(*para):avg=sum(para)
/len(para)
#注意Python2.x与Python3.x对除法运算符“/”的解释不同g=
[iforiinparaifi>avg]
return
(avg,)
+tuple(g)
print(demo2(1,
2,
3,
4))(2.5,3,4)元组的+运算5.7案例精选例2:编写函数,接收任意多个实数,返回一个元575.7案例精选例3:编写函数,接收字符串参数,返回一个元组,其中第一个元素为大写字母个数,第二个元素为小写字母个数。def
demo3(s):result=
[0,
0]
forchins:
if
'a'
<=ch<=
'z':result[1]
+=
1
elif
'A'
<=ch<=
'Z':result[0]
+=
1
returnresult
print(demo3('aaaabbbbC'))[1,8]ch.islower()ch.isupper()5.7案例精选例3:编写函数,接收字符串参数,返回一个元组585.7案例精选例4:编写函数,接收包含20个整数的列表lst和一个整数k作为参数,返回新列表。处理规则为:将列表lst中下标k之前的元素逆序,下标k之后的元素依序,然后将整个列表lst中的所有元素逆序。def
demo4(lst,k):x=lst[:k]x.reverse()y=lst[k:]y.reverse()r=x+yr.reverse()
returnr
lst=list(range(1,
21))print(lst)print(demo4(lst,
5))[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20][6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,1,2,3,4,5]5.7案例精选例4:编写函数,接收包含20个整数的列表ls595.7案例精选例5:编写函数,接收整数参数t,返回斐波那契数列中大于t的第一个数。def
demo5(t):a,b=
1,
1
whileb<t:a,b=b,a+b
else:
returnb
print(demo5(50))55fib(n)=fib(n-1)+fib(n-2)a保存fib(n-1)b保存fib(n-2)5.7案例精选例5:编写函数,接收整数参数t,返回斐波那契605.7案例精选例6:编写函数,接收一个包含若干整数的列表参数lst,返回一个元组,其中第一个元素为列表lst中的最小值,其余元素为最小值在列表lst中的下标。注意:你的运行结果可能不一样!importrandomdef
demo6(lst):m=min(lst)result=
(m,)
forindex,valueinenumerate(lst):
ifvalue==m:result=result+
(index,)
returnresult
x=
[random.randint(1,
20)
foriinrange(50)]print(x)print(demo6(x))minenumerateoperator+random.randintlistcomprehension建议result使用list,而不是tuple!5.7案例精选例6:编写函数,接收一个包含若干整数的列表参615.7案例精选例7:编写函数,接收一个整数t为参数,打印杨辉三角形前t行。def
demo7(t):
print([1])
print([1,
1])line=
[1,
1]
foriinrange(2,t):r=
[]
forjinrange(0,len(line)
-
1):r.append(line[j]
+line[j+
1])line=
[1]
+r+
[1]
print(line)
demo7(10)下一行相比上一行多了两个数,最前面和最后为1,中间的各项都是上一行中连续两项之和5.7案例精选例7:编写函数,接收一个整数t为参数,打印杨625.7案例精选(补充)例7:编写函数,接收一个整数t为参数,打印杨辉三角形前t行。def
demo7_(t):line=
[1]i=
-1
foriinrange(t-1):
print(line)
line=
[sum(i)
foriinzip([0]
+line,line+
[0])]
ifi>=0
ort==
1:
print(line)
def
pas_triangles():a=
[1]
while
True:
yieldaa=
[sum(i)
foriinzip([0]
+a,a+
[0])]
def
demo7__(t):
g=pas_triangles()
forninrange(t):
print(next(g))5.7案例精选(补充)例7:编写函数,接收一个整数t为参数635.7案例精选例8:编写函数,接收一个正偶数为参数,输出两个素数,并且这两个素数之和等于原来的正偶数。如果存在多组符合条件的素数,则全部输出。importmathdef
IsPrime(n):m=int(math.sqrt(n))
+
1
foriinrange(2,m):
ifn%i==
0:
return
False
return
True
def
demo8(n):
ifisinstance(n,int)
andn>
0
andn%
2
==
0:
foriinrange(3,int(n/
2)
+
1):
ifIsPrime(i)
andIsPrime(n-i):
print(i,
'+',n-i,
'=',n)demo8(60)5.7案例精选例8:编写函数,接收一个正偶数为参数,输出两645.7案例精选例9:编写函数,接收两个正整数作为参数,返回一个数组,其中第一个元素为最大公约数,第二个元素为最小公倍数。def
demo9(m,n):
ifm>n:m,n=n,mp=m*n
whilem!=
0:r=n%mn=mm=r
return
(int(p/n),n)
print(demo9(20,
30))辗转相除法(欧几里德法):(m,n)(n%m,m)….(0,n)思考题:采用递归方式实现最大公约数5.7案例精选例9:编写函数,接收两个正整数作为参数,返回655.7案例精选例10:编写函数,接收一个所有元素值互不相等的整数数列x,和一个整数n,要求将值n的元素作为支点,将列表中所有值小于n元素全部放到n前面,所有值大于n的元素放到n后面。importrandomdef
demo10(x,n):
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 危险化学品泄漏事故应急处置方案
- 农产品市场营销渠道拓展策略方案
- 客户流失原因分析改进方案
- 足疗按摩服务标准流程
- 受限空间作业事故处置规程
- 仔猪早期断奶培育管理规范
- 职业病危害因素检测与评价规范
- 水产池塘水质在线监测预警方案
- 理疗仪器设备使用规范
- 植保无人机植保作业技术规范
- 小学奥数几何模块-等高模型、等积变形、一半模型
- 19.SL-T19-2023水利基本建设项目竣工财务决算编制规程
- 排水管网清淤疏通方案(技术方案)
- 计算机辅助项目管理课程设计
- 年产2亿片的萘普生的车间设计
- 费马点练习题
- 新修水库施工方案
- JJF 1903-2021冲击响应谱试验机校准规范
- GB/T 12060.5-2011声系统设备第5部分:扬声器主要性能测试方法
- GESE3英国圣三一口语考试3级准备资料【精选】
- 项目质量管理案例
评论
0/150
提交评论