总结Python编程中函数的使用要点
为何使用函数
编写函数 >>def语句 def <name>(arg1,arg2,... argN): <statements> 通常情况下,函数体中会有一个return语句,可以出现在函数体的任何位置,它表示函数调用的结束,并将结果返回至函数调用处。但是return语句是可选的,并不是必须的。从技术角度上说,一个没有返回值的函数自动返回了none对象,但是这个值可以被忽略掉。 >>def语句是实时执行的 if test: def func(): ... else: def func(): ... ... func() 它在运行时简单地给一个变量名进行赋值。与C语言这样的编译语言不同,Python函数在程序运行之前并不需要全部定义,更确切地说,def在运行时才评估,而在def之中的代码在函数调用时才会评估。 就像Python中其他语句一样,函数仅仅是对象,在程序执行时它清除地记录在了内存之中。实际上,除了调用之外,函数允许任意的属性附加到记录信息以供随后使用: othername=func #Assign function object othername() #Call func again func() #call object func.attr=value #attach attribute 一个例子:定义和调用 def times(x,y): return x*y times(2,4) #return 8 times(3.12,4) #return 12.56 times('Ni',4) #return 'NiNiNi' 上面代码中对函数的三次调用都能正确运行,因为”*“对数字和序列都有效,在Python我们从未对变量、参数或者返回值有过类似的声明,我们可以把times用作数字的乘法或是序列的重复。 换句话说,函数times的作用决定于传递给它的参数,这是Python的核心概念之一。 需要强调的是,如果我们传入了一个不支持函数操作的参数,Python会自动检测出不匹配,并抛出一个异常,这样就能减少我们编写不必要的类型检测代码。 >>局部变量 函数设计概念
>>间接函数调用 把函数赋值给其他变量: def echo(message): print(message) x = echo x('Indirect call!') #Prints:Indirect call! 传递给其他函数: def indirect(func,arg): func(arg) indirect(echo,'Argument call') #Prints:Argument call 把函数对象填入到数据结构中: schedule=[(echo,'Spam!'),(echo,'Ham!')] for (func,arg) in schedule: func(arg) 从上述的代码中可以看到,Python是非常灵活的! >>函数内省 func.__name__ dir(func) 内省工具允许我们探索实现细节,例如函数已经附加了代码对象,代码对象提供了函数的本地变量和参数等方面的细节: dir(func.__code__) func.__code__.co_varnames func.__code__.co_argument 工具编写者可以利用这些信息来管理函数。 >>函数属性 func.count=0 func.count+=1 func.handles='Button-Press' 这样的属性可以用来直接把状态信息附加到函数对象,而不必使用全局、非本地和类等其他技术。和非本地不同,这样的属性信息可以在函数自身的任何地方访问。这种变量的名称对于一个函数来说是本地的,但是,其值在函数退出后仍然保留。属性与对象相关而不是与作用域相关,但直接效果是类似的。 >>Python3.0中的函数注解 从语法上讲,函数注解编写在def头部行,对于参数,它们出现在紧随参数名之后的冒号之后;对于返回值,它们编写于紧跟在参数列表之后的一个->之后。 def func(a:'spam',b:(1,10),c:float) -> int: return a+b+c 注解和没注解过的函数在功能和使用上完全一样,只不过,注解过的函数,Python会将它们的注解的数据收集到字典中并将它们附加到函数对象自身。参数名变成键,如果编写了返回值注解的话,它存储在键return下,而注解的值则是赋给了注解表达式的结果: func.__annotations__ #Prints:{'a':'spam','c':<class 'float'>,'b':(1,'return':<class 'int'>} 注意点 如果编写了注解的话,仍然可以对参数使用默认值,例如:a:'spam'=4 意味着参数a的默认值是4,并且用字符串'spam'注解它。 除了def语句之外,Python还提供了一种生成函数对象的表达式形式。由于它与LISP语言中的一个工具很相似,所以称为lambda。就像def一样,这个表达式创建了一个之后能够调用的函数,但是它返回了一个函数而不是将这个函数赋值给一个变量名。这也就是lambda有时叫做匿名函数的原因。实际上,它们常常以一个行内函数定义的形式使用,或者用作推迟执行一些代码。 >>lambda表达式 lambda argument1,argument2,...argumentN:expression using arguments 由lambda表达式所返回的函数对象与由def创建并赋值后的函数对象工作起来是完全一样的,但是lambda有一些不同之处让其在扮演特定的角色时很有用。 lambda是一个表达式,而不是一个语句。 def func(x,y,z):return x+y+z func(2,3,4) #Return 9 f = lambda x,z : x + y + z f(2,4) #Return 9 默认参数也能在lambda中使用 x=(lambda a="fee",b="fie",c="foe": a+b+c) x("wee") #Prints:'weefiefoe' 在lambda主体中的代码像在def内的代码一样都遵循相同的作用域查找法则。 >>为什么要使用lambda lambda通常用来编写跳转表: L=[lambda x: x ** 2,lambda x: x ** 3,lambda x: x ** 4] for f in L: print(f(2)) #Prints:4,8,16 print(L[0](3)) #Prints:9 实际上,我们可以用Python中的字典或者其他数据结构来构建更多种类的行为表: key='got' {'already':(lambda: 2+2),'got':(lambda: 2*4),'one':(lambda: 2 ** 6)}[key]() #Prints:8 这样编写代码可以使字典成为更加通用的多路分支工具。 最后需要注意的是,lambda也是可以嵌套的 ((lambda x:(lambda y: x+y))(99))(4) #Prints:103 在序列中映射函数:map map函数会对一个序列对象中的每个元素应用被传入的函数,并且返回一个包含了所有函数调用结果的一个列表。 counters=[1,2,4] def inc(x):return x+10 list(map(inc,counters)) #[11,12,13,14] 由于map期待传入一个函数,它恰好是lambda最常出现的地方之一。 list(map((lambda x: x+10),counters)) #[11,14] 函数式编程工具:filter和reduce 在Python内置函数中,map函数是用来进行函数式编程的这类工具中最简单的内置函数代表。所谓的函数式编程就是对序列应用一些函数的工具。例如过滤出一些元素(filter),以及对每对元素都应用函数并运行到最后的结果(reduce)。 list(filter((lambda x: x>0),range(-5,5))) #[1,4] 序列中的元素若其返回值是真的话,将会被加入到结果列表中。 reduce接受一个迭代器来处理,但是,它自身不是一个迭代器,它返回一个单个的结果。 from functools import reduce #Import in 3.0,not in 2.6 reduce((lambda x,y: x+y),[1,4]) #Return:10 reduce((lambda x,y: x*y),4]) #Return:24 上面两个reduce调用,计算了一个列表中所有元素的累加和与累积乘积。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |