2023.3.9学习记录Python

您所在的位置:网站首页 斐波拉契0618 2023.3.9学习记录Python

2023.3.9学习记录Python

2023-03-15 14:32| 来源: 网络整理| 查看: 265

生成器

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