python 生成器和迭代器通俗理解 python生成器表达式

先来学几个英文单词,本文统一使用英文单词表示以下概念:
「」:「可迭代对象」
【python 生成器和迭代器通俗理解python生成器表达式】「」:「迭代器」
「」:「生成器」
本文的重点是「」,之所以上来就说这3个概念,是因为:
只不过是和的一种简单形式 。
用类的形式写/,要定义类,并包含至少三个函数:,和,但用只要定义一个函数就搞定了 。
我在面试程序员的时候,连续几个号称资深的程序员,回答的问题都回答的不好 。如果你能理解透彻这篇文章,对你的加薪作用可能不止一千 。
虽然有标题党的嫌疑,但具有实在的意义 。所以既然进来了,就耐心读下去吧 。一周能理解透一个重要概念,假以时日,你就是高手 。
如果你对和一无所知,建议先阅读本文的姊妹篇:
『终结者 #2』可迭代对象() vs 迭代器() vs 生成器 ()
我们先用「/」的方式来定一个「随机数生成器」,我把它命名为「」,它的功能是:
随机生成若干个1到100之间的随机数 。
class ():
def (self, total):
self.count = 0
self.total = total
def (self):
self
def (self):
if self.count == self.total:
raise
= .(1, 100)
self.count += 1
使用上面的类生成88个随机数:
for i in (88):
print(i)
这是一个类,包含,和个函数:
(100)调用函数创建了一个可以生成100个随机数的对象 。
for语句循环这个对象的时候首先调用函数获取,也就是这个对象本身 。
然后for不停调用函数做循环,直到抛出异常 。
整个过程有点小复杂,也难以理解 。的出现就是为了简化这种复杂的写法 。
实现同样的功能,只需要一个「函数」就够了:
def (total):
for _ in range(0, total):
yield .(1, 100)
调用过程不变:
for i in (88):
print(i)
for循环过程
结合上面的的例子,我们看一下for循环的过程:
调用函数(88):,并不会马上执行函数中的代码,而是返回一个对象 。
for循环通过内置的next函数调用这个对象,直到对象抛出异常为止 。
试验一下:
def (total):
for _ in range(0, total):
yield .(1, 100)
g = (88)
print(type(g))
执行上面这段代码,会打印出:
函数中没有语句,只有「yield」语句 。所以生成器就是:「有yield关键词的函数」 。
也可以有语句,语句就相当于抛出了异常,会结束函数 。
使用next()函数执行中的代码,上面的for循环也是这个原理 。
当代码执行到「yield」语句的时候,yield会返回一个值给调用者,然后函数暂定在原地,等待下次调用 。
下次调用会从上次暂定的地方继续执行代码 。这个过程会重复直到所有代码都执行完成,或者抛出了异常 。
来看一个例子:
#
def ():
print('这是第一步,你好!!')
yield
print('这是第二步,你还好吗?')
yield
print('这是第三步,再见!')
s = ()
next(s)
next(s)
next(s)
运行一下,打印的结果如下:
---第一次调用
这是第一步,你好!!
---第二次调用
这是第二步,你还好吗?
---第三次调用
这是第三步,再见!
(mostcall last):
File "/Users//git////gen.py", line 47, in
next(s)
说明一下:
yield关键词会让函数暂停,也可以没有返回值
「可以把理解成有状态的函数」 。一般的函数没有自己的状态,执行一次就结束了 。但是有自己的状态可以被多次调用 。