首页 > 代码库 > python函数(三)

python函数(三)

    今天介绍其他几类函数:协同函数,递归,匿名函数

目录:

    协程函数

    递归

    匿名函数

1.协程函数

    上次将了生成器表达式:含有yield的函数。这次讲下yield的其它用途:协程函数:

    函数中还有另外一种yield的表达式形式:x=yield 。

    python引入的与生成器相关的最后一个特性是提供了与next方法调用进行交互的功能,yiled表达式,通过send方法传递给next。下面看一个例子:

 1 >>> def psychologist():
 2     print(please tell me your problems)
 3     while True:
 4         answer=yield
 5         if answer is not None:
 6             if answer.endswith(?):
 7                 print("don‘t ask yourself too much questions")
 8             elif good in answer:
 9                 print("a that‘s good, go on")
10             elif bad in answer:
11                 print("don‘t be so negative")
12 
13 >>> free=psychologist()
14 >>> next(free)
15 please tell me your problems
16 >>> free.send(i feel bad)
17 dont be so negative
18 >>> free.send("why i shouldn‘t ?")
19 dont ask yourself too much questions
20 >>> free.send(ok then is should find what is good for me)
21 a thats good, go on

  free是一个生成器函数,我们运行next方法的时候程序停止在answer=yield处停止,我们这是使用send方法给yield表达式传递内容,函数继续执行之后的代码部分,并再次停止在answer=yield处,等待我们通过send函数再次传递数据。

    现在有一点不方便的地方就是我们在执行send函数之前必须使用next函数初始化一下生成器函数,这个我们协程函数带来了点麻烦,每次使用的时候都需要先next(生成器函数)一次。前面学过装饰器,我们可以使用装饰器的例子首先在装饰器中执行next方法,之后将生成器函数返回给调用处,这样调用的地方就可以直接使用send方法进行处理。

 1 def init(func):
 2     def _init(*args,**kwargs):
 3         res=func(*args,**kwargs)
 4         next(res)                       #先next,之后返回生成器函数
 5         return res
 6     return _init
 7 
 8 
 9 @init
10 def psychologist():
11     print(please tell me your problems)
12     answer=yield
13     while True:
14         if answer is not None:
15             if answer.endswith("?"):
16                 print("don‘t ask yourself too much questions")
17             elif goodin answer:
18                 print("a that‘s good, go on")
19             elif bad in answer:
20                 print("don‘t be so negative")
21 
22 free=psychologist()
23 free.send(i feel bad)
24 free.send("why i shouldn‘t ?")
25 free.send("ok then is should find what is good for me")

    2.递归

    递归:程序调用本身的编程方法叫做递归,这种编程方法通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

    下面写一个求fibonacci函数的例子:

 1 def fibonacci(n):
 2     if n<=0:  #递归的终止条件
 3         return 0
 4     elif n==1:   #递归的终止条件
 5         return 1
 6     else:
 7         return fibonacci(n-1)+fibonacci(n-2)
 8 
 9 f=[fibonacci(n) for n in range(10)]
10 print(f)
11 结果:[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

 

    3.匿名函数

  有时我们需要对数值进行简单的操作,比如,求x和y的值,我们可能会写如下函数:

1 def x_multi_y(x,y):
2     return x*y

 

     这样以来很简单的操作都需要额外定义函数,不够优雅,于是python从函数式编程语言中引进了lambda函数,lambda实现匿名的函数,如下的例子:

1 #def x_multi_y(x,y):
2     #return x*y
3 
4 a=lambda x,y : x * y
5 a(10,20)
6 结果:200

 

   从上面可以看到lambda表达式可以起到一个函数的作用,省去了单独定义函数的麻烦,lambda关键字后面是参数,冒号后面是返回的表达式结果。用一个变量接受该结果,以后就可以使用 ”变量()“ 的方式调用lambda表达式完成计算了。

    时常与lambda搭配一起使用的函数有 map(),reduce(),filter(),下面我们通过例子来认识它们:

map(func,*iterables): map的作用就是将 函数 func 作用与每一个iterables对象,产生新的结果集,看例子:

1 >>> a=map(lambda x: x**2,[1,2,3,4,5])     #求[1,2,3,4,5]每个元素的平方,之后返回新的序列
2 >>> list(a)
3 [1, 4, 9, 16, 25]
4 >>> 

 

reduce 在python3中放到了模块 functools中,reduce(func,sequence,[initial])每次从sequence中取两个元素,传递给func函数操作,之后在从sequence中取一个元素和之前的结果凑成两个元素传递给func函数,知道sequence被迭代完,最后reduce的结果是一个值,如果给了initial。则将initial作为初始值,从sequence中取出一个值传递给func函数,后续每次从sequence中取一个值传递给func函数操作,最终返回一个值。如下的例子:

1 >>> from functools import reduce
2 >>> reduce(lambda x,y:x+y,[1,2,3,4,5])      #计算((((1+2)+3)+4)+5)=15
3 15
4 >>> reduce(lambda x,y:x+y,[1,2,3,4,5],10)    #以10作为初始值,计算 (((((10+1)+2)+3)+4)+5)=25
5 25

 

filter(func,iterable) 将可迭代对象的元素传入func中,如果结果为True,则保留,如果为False,则继续下一次迭代。就是将iterable中元素迭代到func中,返回结果为True的元素。

1 >>> a=filter(lambda x:x%2 ,[1,2,3,4,5,6,7,8,9,0])   #计算基数
2 >>> a
3 <filter object at 0x0000000003580F98>
4 >>> list(a)
5 [1, 3, 5, 7, 9]

 

python函数(三)