Skip to content

生成器

函数体中出现 yield 时,它是生成器函数。调用函数不会立即执行函数体,而是返回生成器对象;生成器本身就是迭代器。

py
def gen_num():
    print('start generator')
    yield 1
    yield 2
    yield 3

    return 4

print(gen_num)

gen = gen_num() # 生成器对象

print(gen)

print(next(gen))
print(next(gen))
print(next(gen))

# try:
#     print(next(gen))
# except StopIteration as e:
#     print('generator return value:',e.value)

每次调用 next(gen),生成器从上次暂停处继续,运行到下一个 yield 后再次暂停并产出值。函数结束后生成器耗尽,不能重新开始。

用生成器实现 __iter__

生成器可以代替手写的迭代器类:

py
import re


WORD_RE = re.compile(r'\w+')

class Sentence:
    def __init__(self, text: str) -> None:
        self.text = text
        self.words = WORD_RE.findall(text)

    def __iter__(self):
        for word in self.words:
            yield word


s = Sentence("Hi ice, Hello World!")

it1 = iter(s)

# for word in s:
#     print(word)

# for word in s:
#     print(word)


for word in it1:
    print(word)

for word in it1:
    print(word)

每次 iter(sentence) 都会创建新的生成器,因此同一个 Sentence 可以重复遍历。

惰性产生结果

findall() 会先创建完整的匹配列表;finditer() 配合生成器会按需产生每个匹配结果:

py
from pydoc import text
import re


WORD_RE = re.compile(r'\w+')

class Sentence:
    def __init__(self, text: str) -> None:
        self.text = text

    def __iter__(self):
        # for match in WORD_RE.finditer(self.text):
        #     yield match.group()
        return (match.group() for match in WORD_RE.finditer(self.text))


s = Sentence("Hi ice, Hello World!")

for word in s:
    print(word)
    
print('-------------')

for word in s:
    print(word)

适合大文件、流式数据和计算成本较高的数据。

生成器表达式

生成器表达式使用圆括号,结果按需产生;列表推导会立即创建完整列表。

python
squares = (x * x for x in range(5))