2023.3.9学习记录Python |
您所在的位置:网站首页 › 斐波拉契0618 › 2023.3.9学习记录Python |
生成器 1、通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。 而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。 在Python中,这种一边循环一边计算的机制,成为生成器:generator。 要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式[]改成(),就创建了一个generator: L=[x*x for x in range(10)] print(L) g=(x*x for x in range(10)) print(g) #打印结果 创建L和g的区别仅在于最外层的[]和(),L是一个list。而g是一个generator。 我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢? 如果要一个一个打印出来,可以通过next()函数获得generrator的下一个返回值: next(g) #打印结果:0 generator保存的是算法,每次调用next(g),就计算出g的下一个元素值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。 上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象; g=(x*x for x in range(10)) for n in g: print(n) 所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不关系StopIteration的错误。 比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可以由前面两个数相加得到: 1, 1, 2, 3, 5, 8, 13, 21, 34, ... 斐波拉契数列表用列表生成式写不出来,但是,用函数把它们打印出来却很容易: #用函数打印斐波拉契数列 def fib(max): n,a,b=0,0,1 while n> o = odd() >>> next(o) step 1 1 >>> next(o) step 2 3 >>> next(o) step 3 5 >>> next(o) Traceback (most recent call last): File "", line 1, in StopIteration 调用该generator函数时,首先要生成一个generator对象,然后用next()函数不对获取下一个返回值: 可以看到,odd不是普通函数,而是generator函数,在执行过程中,遇到yield就终端,下次又继续执行。执行3次yield后,已经没有yield可以执行了, 所以,第四次调用next(o)就报错 ****注意:调用generator函数会创建一个generator对象,多次调用generator函数会创建多个相互独立的generator 有的同学会发现这样调用next()每次都返回1: 原因在于odd()会创建一个新的generator对象,上述代码实际上创建了3个完全独立的generator,对3个generator分别调用next()当然每个都会返回第一个值。 正确的写法是创建一个generator对象,然后不对对这个generator对象调用next(): >>> g = odd() >>> next(g) step 1 1 >>> next(g) step 2 3 >>> next(g) step 3 5 回到fib的例子,我们在循环过程中不断调用yield,就会不断终端。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。 >>> for n in fib(6): ... print(n) ... 1 1 2 3 5 8 2、练习题练习 杨辉三角定义如下: 1 / \ 1 1 / \ / \ 1 2 1 / \ / \ / \ 1 3 3 1 / \ / \ / \ / \ 1 4 6 4 1 / \ / \ / \ / \ / \ 1 5 10 10 5 1 把每一行看做一个list,试写一个generator,不断输出下一行的list: n = eval(input("输入要打印的行数:")) triangle = [[1], [1, 1]] for i in range(2, n): # 已经给出前两行,求剩余行 print(i) pre = triangle[i-1] # 上一行 cul = [1] # 定义每行第一个元素 for j in range(i-1): # 算几次 cul.append(pre[j]+pre[j+1]) # 每个数字等于上一行的左右两个数字之和。 cul.append(1) # 添加每行最后一个元素 triangle.append(cul) print(triangle) print("普通输出:{}".format(triangle)) for i in range(n): # 按等边三角形格式输出 s = " "*(n-i-1) for j in triangle[i]: s = s + str(j)+" " print(s) #打印结果 1 1 2 3 5 8 输入要打印的行数:5 2 [[1], [1, 1], [1, 2, 1]] 3 [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]] 4 [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]] 普通输出:[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]] 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |