python—函数进阶-斐波那契数列

上次说到生成器的调用next(),这样很不方便,需要手动调,我们一般是循环着调,while ,for都可以

a = (i for i in range(5))
for i in a:
   print(i)

0
1
2
3
4   # 执行结果
#和手动调的区别是没了的话就会自动终止循环。就跳出来了


#换成while
a = (i for i in range(5))
while True:
   next(a)

0
1
2
3
4
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
StopIteration    # 执行结果,会报错


#所以一般会用for循环,相当于错误内部就给消化了  


补充:其实range(10)底层就是用生成器实现的,也就是每循环一次加一,再python3.x里,range(10)的执行结果是range(0,10),而在python2.7里,结果是直接生成了一个列表[0,1,2,3,4,5,6,7,8,9],这是因为python3中他不是一个普通的range(),是一个公式,就根本没有创建,只有循环到了才创建这个值,但是再python2 里有和python3里range()方法相同的是xrange()。

前面所讲的加1是最简单的,生成器是可以做复杂的算法的。再列表生成式里最复杂的最多写三元运算,而要是做更复杂的,就需要用函数来做这个生成器。



比如,数学上著名的斐波那契数列,(除了第一个和第二个数之外,任意两个数都可由前两个数相加得到)1,1,2,3,5,8,13,21,34......(没什么用,就是一个规律)

如果把前15个数相加,斐波那契数列用列表生成式写不出来,但是可以用函数把他轻松的打印出来

def fib(max):
    n, a, b = 0, 0, 1
    while n< max:
        print(b)
        a, b = b, a+b
        n = n+1
    return 'done'
  

注意赋值语句:a, b = b, a+b

试一下:

fib(15)
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
'done'  # 执行结果
  

把他变成生成器只需要一步

def fib(max):
    n, a, b = 0, 0, 1
    while n< max:
        yield b
        a, b = b, a+b
        n = n+1
    return 'done'
print(fib(15))

<generator object fib at 0x0000019878D244C0>  #执行结果


#接下来调用
def fib(max):
    n, a, b = 0, 0, 1
    while n< max:
        yield b  #只要函数中出现了yield,就变成了一个生成器,它的作用就是把函数的执行过程冻结在这一步,并且把 b 的值返回给next
        a, b = b, a+b
        n = n+1
    return 'done'
f = fib(15)
print(next(f))
print(next(f))
print(next(f))
print(next(f))

1
1
2
3   # 执行结果


# 换成循环的方式调用
def fib(max):
    n, a, b = 0, 0, 1
    while n< max:
        yield b  
        a, b = b, a+b
        n = n+1
    return 'done'
f = fib(15)
for i in f:
   print(i)

1
1
2
3
5
8
13
21
34
55
89
144
233
377
610   # 执行结果

#分析
def fib(max):
    n, a, b = 0, 0, 1
    while n< max:
        print('yemao')
        yield b  #函数到这儿并没有返回就结束了,而是冻结了,接下来怎么继续往下走呢
        print(b)
        a, b = b, a+b
        n = n+1
    return 'done'
f = fib(15)
print(f)  并不会有执行结果,不会调用,只是生成了一个生成器

next(f)# 调用next才会被执行

#yield比之前的函数好的地方其实是,函数一执行,就会再函数里面打印等结果,不能往外返回, #而用yield就可以在执行的过程中把想要的值返回出来, #yield以后, 函数外面加()根本不会调用,而是生成了一个生成器

  

#如果要中途终止这个生成器
def range2(n): count = 0 while count < n: print('count', count) count += 1 sign = yield count #return if sign == 'stop': print('---sign', sign) break return 3333 new_range = range2(3) n1 = next(new_range) new_range.send('stop') #next只能是唤醒生成器并执行 #send可以是唤醒并执行,还可以发送给一个信息到生成器内部 count 0 Traceback (most recent call last): ---sign stop File "E:/pycharm/pyCharm/考核/lianxi.py", line 16, in <module> new_range.send('stop') StopIteration: 3333 # 执行结果

  

  

原文地址:https://www.cnblogs.com/xiaobai-yemao/p/8783932.html