列表生成式:
用遍历的方式生成的list,比如:
my_list1 = []
for x in range(1, 20):
my_list1.append(x * x + 2)
print(my_list1)能用遍历生成的list, 可以用简化的方式实现上面的代码,但从易读性的角度看,还是上面的写法好:
my_list2 = [x*x + 2 for x in range(1, 20)] # for前面的 x*x + 2就是计算的语句, for后面的语句就是循环迭代
print(my_list2)两层循环也可以用上面的方式实现,这种简化写法就是“列表生成式”
my_list3 = [m - n for m in range(1,20) for n in range(2,5)]
print(my_list3)[3, 6, 11, 18, 27, 38, 51, 66, 83, 102, 123, 146, 171, 198, 227, 258, 291, 326, 363]
[3, 6, 11, 18, 27, 38, 51, 66, 83, 102, 123, 146, 171, 198, 227, 258, 291, 326, 363]
[-1, -2, -3, 0, -1, -2, 1, 0, -1, 2, 1, 0, 3, 2, 1, 4, 3, 2, 5, 4, 3, 6, 5, 4, 7, 6, 5, 8, 7, 6, 9, 8, 7, 10, 9, 8, 11, 10, 9, 12, 11, 10, 13, 12, 11, 14, 13, 12, 15, 14, 13, 16, 15, 14, 17, 16, 15]对字典、字符串的遍历也可,用来写生成式:
student_dict = {"张三": 15, "李四": 14, "王五": 16}
# k + "年龄为:" + str(v) 用来拼接字符串,v是int类型,所以先转换为字符串
print([k + "年龄为:" + str(v) for k, v in student_dict.items()])['李四年龄为:14', '张三年龄为:15', '王五年龄为:16']生成器(基于列表生成式的生成器):
列表生成式会一次性生成全部的元素计算出来并存储到内存,在列表规模比较大的时候会占用较多的内存;采用生成器,则是用到一个元素,才会去计算一个元素,节约了内存消耗。
生成器的创建,将上面的生成式的[]改成(),就变成了一个生成器,如下方代码;因为gen1创建出来后,并没有存储的值,所以打印后展现的是一个生成器对象地址。 要访问它的值,需要用到next()函数,每用next()调用生成器一次,生成器就生成一个元素,并且下一行要执行的代码的位置会被记录,直到在此调用next();再次调用next(),生成器函数会从它上次离开的地方开始。
gen1 = (x*x + 2 for x in range(1, 20))
print(gen1)
i = 0
while i < 10:
print(next(gen1))
i += 1D:\pythonProjects\venv\Scripts\python.exe D:/pythonProjects/100Prac/55.py
<generator object <genexpr> at 0x0000000000B65150>
3
6
11
18
27
38
51
66
83
102这种生成还可以用for循环访问:
gen1 = (x*x + 2 for x in range(1, 5))
print(gen1)
for i in gen1:
print(i)D:\pythonProjects\venv\Scripts\python.exe D:/pythonProjects/100Prac/55.py
<generator object <genexpr> at 0x0000000001135150>
3
6
11
18生成器(基于函数的生成器):
还有一种生成器的创建方法,就是基于改造函数。我尝试了一下,将改造要点列举在下面:
1. 将函数返回值从return变为yield。
2. 遇到要改造的函数中有循环,需要将其改造为无限循环
3. 调用的方式与函数也不一样,要先创建生成器对象,再进行调用 (因为只有有一个明确的对象后,才能记录代码执行到什么位置了)
下面改造下面的普通函数来说明:
def fib(max):
n, a, b = 0, 0, 1
fib_list = []
while n < max:
fib_list.append(b)
a = b
b = a + b
n += 1
return fib_list
for i in fib(4):
print(i)D:\pythonProjects\venv\Scripts\python.exe D:/pythonProjects/100Prac/56-1.py
1
2
4
8step1: 首先将return改造为yield,因为上面的函数是一次性计算了所有需要的b,然后返回一个b值的列表。这个对于生成器而言就不合适,生成器的本意是,你调用我一次,我返回一个b值,你再调用一次,我在继续运行代码,返回下一个b值。所以需要将列表去掉,将返回的内容直接指定为b
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a = b
b = a + b
n += 1
for i in fib(4):
print(i)step2: 将循环改为无限循环,原因是为了避免“StopIteration”异常,因为next()函数现在还并有智能到如同 for..in..,知道什么时候该停下来,一但调用超出循环范围,程序就会异常。 改为无限循环后,就不会出现异常了。
def fib():
a, b = 0, 1
while True:
yield b
a = b
b = a + b
for i in fib(4):
print(i)step 3: 函数已经改造完毕,接着调用也需要改造,关键是要创建生成器对象,再用next()调用对象。
def fib():
a, b = 0, 1
while True:
yield b
a = b
b = a + b
f = fib()
for i in range(1, 5):
print(next(f))运行结果如下:
D:\pythonProjects\venv\Scripts\python.exe D:/pythonProjects/100Prac/56.py
1
2
4
8例子三: 杨辉三角
def triangles():
L = [1]
while True:
yield L
L = [1] + [L[i] + L[i+1] for i in range(len(L)-1)] + [1]
a = triangles()
for i in range(10):
print(next(a))[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
本文详细介绍了Python中列表生成式的使用方法及其优势,并深入探讨了生成器的两种创建方式——基于列表生成式和基于函数。通过实例展示了如何利用生成器节省内存资源,以及如何改造普通函数为生成器。

被折叠的 条评论
为什么被折叠?



