python-生成器、迭代器理解

迭代器

顾名思义,迭代器就是用于迭代操作(for 循环)的对象,它像列表一样可以迭代获取其中的每一个元素,任何实现了__next__ 方法 (python2 是 next)的对象都可以称为迭代器。

它与列表的区别在于,构建迭代器的时候,不像列表把所有元素一次性加载到内存,而是以一种延迟计算(lazy evaluation)方式返回元素,这正是它的优点。比如列表含有中一千万个整数,需要占超过400M的内存,而迭代器只需要几十个字节的空间。因为它并没有把所有元素装载到内存中,而是等到调用 next 方法时候才返回该元素(按需调用 call by need 的方式,本质上 for 循环就是不断地调用迭代器的next方法)。

以斐波那契数列为例来实现一个迭代器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Fib(object):
def __init__(self, n):
self.pre_pre = 0
self.pre = 1
"""
:param n: int, 指明生成数列的前n个数
"""
self.n = n
# index用来保存当前⽣成到数列中的第几个数了
self.index = 0

def __next__(self):
if self.n > 0 and self.index < self.n:
value = self.pre
self.pre_pre,self.pre = self.pre, self.pre_pre+self.pre
self.index +=1
return value
else:
return StopIteration()

def __iter__(self):
return self

def main():
# 传入 10, 输出10位斐波那契数列 1,1,2,3,5,8,13,21,34,55
resp=[]
n=10
f = Fib(n)
for i in range(0,n):
resp.append(f.__next__())
print(resp)
if __name__ == '__main__':
main()
#[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

生成器

生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写iter()和next()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式来生成值。用生成器来实现斐波那契数列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from itertools import islice


def fib():
prev, curr = 0, 1
while True:
yield curr # 循环探针yield
prev, curr = curr, curr + prev


def main():
f = fib()
resp = list(islice(f, 0, 10)) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
return resp


if __name__ == '__main__':
print(main())

python 面试题集锦

  1. 如何在Python中实现多线程

    Python有一个多线程库,但是用多线程来加速代码的效果并不是那么的好,

    Python有一个名为Global Interpreter Lock(GIL)的结构。GIL确保每次只能执行一个“线程”。一个线程获取GIL执行相关操作,然后将GIL传递到下一个线程。

    虽然看起来程序被多线程并行执行,但它们实际上只是轮流使用相同的CPU核心。

    所有这些GIL传递都增加了执行的开销。这意味着多线程并不能让程序运行的更快。

    是否可以考虑协程?

  2. 循环names列表,打印每个元素的索引值和元素,当索引值为偶数时,把对应的元素改成-1。(考点列表元素,索引循环)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    for index,i in enumerate(names):

    if index%2==0:

    names[index]=-1

    print("索引 %d 为偶数,值已重置 ",index)

    print(names)