列表生成式
在Python语言中,所谓的列表生成式,顾名思义,就是说可以生成list列表的表达式,是Python内置的一种强大的功能。列表生成式即List Comprehensions,列表生成式作用是用来生成列表的,那么其特点也肯定是使用“[]”来去表示的。
例如想对列表里面的数据进行运算后重新生成一个新的列表,如[1,2,3 ... 100],按平常思维就是先定义一个列表c,然后for循环挨个运算,算完了再append添加到c,最后c就是新的列表了:
a = range(1,10)
c = []
for i in a:
c.append(i*i)
print(c) #[1, 4, 9, 16, 25, 36, 49, 64, 81]
使用函数也是如此:
def f(n):
return n**2
a = [f(x) for x in range(5,10)]
print(a) #[25, 36, 49, 64, 81]
生成器
定义:一边循环一边计算的机制,称为生成器(generator);
为什么使用生成器:
通过列表生成式,我们可以直接创建一个列表,列表所有的数据都在内存中,所以大量的数据会非常消耗内存,而生成器一次产生一个值,这样消耗的内存数量将会大大减小,所以想要得到大量的数据,又想占用内存少,就使用生成器(所有的生成器都是一个迭代器)。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
创建一个生成器:只要把一个列表生成式的[]
改成()
,就创建了一个generator:
s = [x * 2 for x in range(1,10)]
print(s) #[2, 4, 6, 8, 10, 12, 14, 16, 18]
a = (x * 2 for x in range(1,10))
print(a) #<generator object <genexpr> at 0x02C2FF70>
通过next()方法打印generator的每一个元素:
a = (x * 2 for x in range(1,10))
print(a) #<generator object <genexpr> at 0x02C2FF70>
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
输出结果:
<generator object <genexpr> at 0x031AFF70>
2
4
6
8
10
12
14
16
18
不断调用next()方法效率太差,正确的使用方法是使用for循环;
a = (x * 2 for x in range(1,10))
for i in a:
print(i)
2
4
6
8
10
12
14
16
18
使用函数打印斐波拉契数列,可以看出,fib
函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
def fib(max):
n , b , a = 0 , 0 , 1
while n < max:
print(a)
b , a = a , b + a
n += 1
fib(10)
1
1
2
3
5
8
13
21
34
55
要把fib
函数变成generator,只需要把print b
改为yield b
就可以了:
def fib(max):
n , b , a = 0 , 0 , 1
while n < max:
yield(a)
#print(a)
b , a = a , b + a
n += 1
g = fib(10)
print(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
<generator object fib at 0x0053FF70>
1
1
2
3
5
8
13
迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式;
迭代器是一个可以记住遍历的位置的对象;
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退;
迭代器有两个基本的方法:iter() 和 next();
字符串,列表或元组对象都可用于创建迭代器;
例如:
l = [1,2,3,4,5]
d = iter(l)
print(d)
print(next(d))
print(next(d))
print(next(d))
print(next(d))
<list_iterator object at 0x02F2DDF0>
1
2
3
4
迭代器对象也可以使用for循环进行遍历:
l = [1,2,3,4,5]
d = iter(l)
print(d)
for i in d:
print(i,end=" ")
<list_iterator object at 0x02B0DE50>
1 2 3 4 5
for循环内部三件事:
1、调用课程迭代对象iter方法,返回一个迭代器对象;
2、不断调用迭代器对象的next方法;
3、处理StopIteration;
小结:
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。