在了解了python的基本数据类型后,现在我们来看一下python中的函数,为了便于维护和更好的实现模块化,程序都会分解为多个函数。下面我将总结一下python函数的特性,装饰器,生成器,协程等,他们都是进行函数编程和数据处理的强大工具。



1.函数的定义

在python中定义函数很简单,使用def关键字。和c++一样python的函数也可以使用默认参数。




defadd(x, y=1):          


               returnx+y          


           >>> add(1)          


           2




python也可以接收任意数量的参数,在最后一个变量前面加星号,python就会把剩下的变量作为元组放入这个变量。



defadd(x, y=1,*args):          


               foriinargs:          


                   x+=i          


               returnx+y          


           >>> add(1,2,3,4,5)          


           15



上面传递的参数都是根据参数的位置赋值给相应的变量,称为位置参数;python还支持显式地参数赋值,称为关键字参数。



defadd(x, y, z, w):          


               printx,y,z,w            


           >>> add(1, z=2, w=3, y=4)          


           1423



注意事项:

  1. 关键字参数的顺序无关紧要。
  2. 位置参数和关键字参数可以一起使用,但关键字参数必须在位置参数后面
  3. 位置参数已经赋值的变量不能再使用关键字参数赋值,比如上面的x已经赋值为1了,后面的关键字参数就不可以再对x赋值。

参数前一个星号表示任意数量的位置参数,两个星号就是任意数量的关键字参数。python会把剩下的关键字参数作为字典放入这个变量。


deffoo(*args,**kwargs):          


               printargs,kwargs            


           >>> foo(1,2,3,4, x=5, y=6)          


           (1,2,3,4) {'y':6,'x':5}



2.装饰器

装饰器是一个函数,主要用于包装另一个函数或类,以修改或增强这个函数或类的行为。装饰器使用@符号表示。



deftrace(func):          


               print'trace'          


               returnfunc          


                      


           @trace          


           deffoo():          


               print'foo'          


                          


           foo()          


           #输出          


           trace          


           foo



第一个函数trace()是装饰器函数,他接收一个函数对象func,并返回函数对象(必须返回,但不一定是func),@trace对函数foo()进行修饰,等价于foo = trace(foo),所以最后调用的foo并不是之前定义的foo(),而是trace(foo)。这个例子是在函数foo调用前做一些修饰,也可以在调用前后做一些事情。



# 修改trace          


           deftrace(func):          


               print'trace'          


               defnewFunc():          


                   print'begin'          


                   func()          


                   print'end'          


               returnnewFunc          


           # 运行foo后输出          


           trace          


           begin          


           foo          


           end



装饰器是函数,当然也可以接收参数。这样的话必须在装饰器函数内部再定义一个新装饰器函数来接收func对象。



deftrace(msg):          


               print'trace'          


               printmsg          


               defnewTrace(func):          


                   defnewFunc():          


                       print'begin'          


                       func()          


                       print'end'          


                   returnnewFunc          


               returnnewTrace          


           @trace('message')          


           deffoo():          


               print'foo'          


                          


           foo()          


           # 输出          


           trace          


           message          


           begin          


           foo          


           end



3.生成器

生成器是一个函数,他生成一个值的序列,用于迭代。生成器使用yield关键字定义。



>>>defcountdown(n):          


               whilen>0:          


                   yieldn          


                   n-=1          


                              


           >>> c=countdown(5)          


           >>> c.next()          


           5          


           >>>next(c)          


           4          


           >>>foriinc:          


               printi          


           321



上面的c就是一个生成器对象,他可以进行迭代来历遍,在countdown函数内遇到yield就会中止并返回n,直到下次调用next。



3.1.生成器表达式

生成器表达式可以生产一个简单的生成器对象。他和for循环类似,使用圆括号,语法为:
(expression for item in iterable if condition) 后面的if可以省略。



>>> a=(2*xforxinxrange(20)ifx%3==0)          


           >>>foriina:          


               printi          


           061218243036



3.2.列表推导表达式

这里再说一下列表推导表达式,他的语法和生成器表达式差不多,使用中括号,他将生产一个新的列表,语法为:
[expression for item in iterable if condition] if同样可以省略



>>> [2*xforxinxrange(20)ifx%3==0]          


           [0,6,12,18,24,30,36]




4.协程

协程与生成器类似,只不过他是接收数据,而生成器是输出数据。同样使用yield关键字,作为右值。



>>>defreceiver():          


               whileTrue:          


                   x=(yield)          


                   print'Got ',x               


           >>> r=receiver()          


           >>> r.next()          


           >>> r.send(12)          


           Got 12          


           >>> r.send('')          


           Got  



协程在使用时必须先next,让程序运行到yield关键字。这时我们可以给他加个装饰器,让他自动运行一次next。



defcoroutine(func):           


               defstart(*args,**kwargs):           


                   g=func(*args,**kwargs)           


                   g.next()          


                   returng          


               returnstart          


                      


           @coroutine          


           defreceiver():          


               whileTrue:          


                   x=(yield)          


                   print'Got ',x             


                      


           r=receiver()          


           r.send(12)          


           # 输出          


           Got 12