目录
1. 可迭代对象
2. 迭代器
迭代器就是用于迭代操作(for 循环)的对象,它像列表一样可以迭代获取其中的每一个元素,任何实现了__next__方法(python2是next方法)的对象都可以称为迭代器。
他与列表的区别在于构建迭代器的时候不像列表把所有元素一次性加载到内存,而是以一种延迟计算方式返回元素,这正是他的优点。比如列表含有一千万个证书,需要占用超过400M的内存,而迭代器只需要几十个字节的空间,因为他并没有把所有元素装载到内存中,而是等到调用next方法时候才返回该元素,本质上for循环就是不断调用迭代器的next方法。
以斐波那契数列为例实现一个迭代器
class Fib:
def __init__(self, n):
self.prev = 0
self.cur = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.n > 0:
value = self.cur
self.cur = self.cur + self.prev
self.prev = value
self.n -= 1
return value
else:
raise StopIteration()
f = Fib(10)
print([i for i in f])
# [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
3. 生成器
普通函数用return返回一个值,还有一种函数用关键字yield来返回值,这种函数叫做生成器函数,函数被调用时会返回一个生成器对象,生成器本质上还是一个迭代器,也是用在迭代操作中,因此他有和迭代器一样的特性,唯一的区别在于实现的方式不一样,后者则更加的简洁。
最简单的生成器函数
def func(n):
yield n*2
print(func)
# <function func at 0x00000000029F6EB8>
g = func(5)
print(g)
# <generator object func at 0x0000000002908630>
a = next(g)
# 10
# 或者使用for
for i in g:
print(i)
# 10
func就是一个生成器函数,调用该函数时返回对象就是生成器g,这个生成器对象的行为和迭代器是非常相似的,可以用在for循环等场景中,注意yield对应的值是在函数被调用时不会立刻返回,而是调用next方法时返回(本质上for循环也是调用next方法)
使用生成器在逼格上要比迭代器高几个等级,没有那么冗长的代码,且性能上一样的高效,使用生成器实现斐波那契数列
def fib(n):
prev, cur = 0, 1
while n>0:
n -= 1
yield cur
prev, cur =cur, prev + cur
f = [i for i in fib(11)]
print(f)
# [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
生成器表达式和列表推导式长得非常像,但是返回的对象不一样,前者返回的是生成器对象,后者返回的是列表
g = (i for i in range(10))
print(type(g))
for i in g:
print(i)
l = [i for i in range(10)]
print(type(l))
for i in l:
print(i)
迭代大数据时,生成器占用更少的的内存