安徽省住建厅网站官网,网络营销名词解释汇总,响应式网站 翻译,赌求网站开发Generators in Python 文章目录 Generators in PythonIntroduction 导言贯穿全文的几句话为什么 Python 有生成器Generator#xff1f;如何获得生成器Generator#xff1f;1. 生成器表达式 Generator Expression2. 使用yield定义生成器Generator 更多Generator应用实例表示无…Generators in Python 文章目录 Generators in PythonIntroduction 导言贯穿全文的几句话为什么 Python 有生成器Generator如何获得生成器Generator1. 生成器表达式 Generator Expression2. 使用yield定义生成器Generator 更多Generator应用实例表示无限的数据流infinite stream of data将多个生成器generators组成管道pipeline Conclusion 结论 Introduction 导言
生成器generator是 Python 中用来生成迭代器Iterators的一个方便而强大的工具。本篇文章将通过一些示例来解释和深入介绍 Python 中的生成器generators。
如果您还没有完全理解 Itreators不用担心请阅读此篇文章。
贯穿全文的几句话 只要一个函数function中使用了 yield 这个关键字就代表这个函数function每次调用时返回的是一个生成器对象 generator object。这个生成器对象的类型是class ‘generator’。 包含 yield 语句的函数function本身并不是生成器generator它仍然是一个函数function。生成器generator是一个类class而不是函数function。 生成器generator是迭代器Iterator的一个子类subclass。 生成器generator保存的是产生item的生成方法/算法而不是items。 next() 函数只能用于生成器generator类型。不能用于函数function。
def func():yield Helloprint(func) # function func at 0x10d55c0d0
print(type(func)) # class functiong1 func()
g2 func()
print(id(g1), id(g2)) # 4519738272 4519739168
print(g1) # generator object func at 0x10d65bba0
print(type(g1)) # class generator
print(next(g1)) # Hello为什么 Python 有生成器Generator
我们可以通过在 Python 类class中实现implementing __iter__() 和 __next__() 特殊方法special methods来获得迭代器Iterator。不过这种方法有点复杂尽管它有助于理解迭代器Iterators的真正工作原理。
通过生成器generators创建迭代器Iterators是一种更好、更方便的方法。事实上生成器就是迭代器的子类the Generator is a subclass of the Iterator。
Iterable可迭代对象、Iterator迭代器 和 Generator生成器 的关系如下 如上图所示Iterator 是 Iterable 的子类Generator 是 Iterator 的子类。
# 源码在_collections_abc.py
class Iterable(metaclassABCMeta):abstractmethoddef __iter__(self): ...# 源码在_collections_abc.py
class Iterator(Iterable):abstractmethoddef __next__(self): raise StopIterationdef __iter__(self): return self# 源码在_collections_abc.py
class Generator(Iterator):def __iter__(self):return selfdef __next__(self):Return the next item from the generator.When exhausted, raise StopIteration.return self.send(None)abstractmethoddef send(self, value):Send a value into the generator.Return next yielded value or raise StopIteration.raise StopIterationabstractmethoddef throw(self, typ, valNone, tbNone):Raise an exception in the generator.Return next yielded value or raise StopIteration....def close(self):Raise GeneratorExit inside generator....生成器Generator与迭代器Iterator具有相同的作用用于保存一个知道如何生成所需元素的方法method。在Python中操作一个大的列表是非常耗时的。如果我们每次只需要获取一个元素element那么生成器generator就是一个很好的选择它可以减少时间和空间成本。
在 Python 中只要一个函数function中使用了 yield 这个关键字就代表这个函数function每次调用时都是返回一个生成器对象 generator object注意包含 yield 语句的函数function本身并不是生成器generator它仍然是一个函数function。生成器generator是一个类class而不是函数function。而 yield 的作用就相当于让 Python 帮我们把一个“串行”的逻辑转换成 iterator 的形式。
生成器generator都是Iterator迭代器对象。
如何获得生成器Generator
1. 生成器表达式 Generator Expression
生成器表达式generator expression是获取生成器generator的最简单方法。它与 列表推导式list comprehensions 非常相似。我们只需将括号brackets改为小括号parentheses。
my_list [i for i in range(8)]
my_generator (i for i in range(8))print(my_list)
print(my_generator)# [0, 1, 2, 3, 4, 5, 6, 7]
# generator object genexpr at 0x7f8fc3ec9a40由于生成器generator保存的是item生成方法而不是items因此我们需要使用 next() 函数逐个获取项目get items one by one这与迭代器Iterator相同。当所有项目items都生成后 next() 函数将引发 StopIteration 错误信息。当然我们也可以使用 for 循环来获取生成器generator中的项目items。
2. 使用yield定义生成器Generator
如果一个函数function包含 yield 语句它就可以产生生成器generators。
def my_generator(maximum):n 0while n maximum:n 1yield nreturn Doneg my_generator(maximum5)
print(g) # generator object my_generator at 0x10e269ba0
print(next(g)) # 1
print(next(g)) # 2
print(next(g)) # 3
print(next(g)) # 4
print(next(g)) # 5
next(g)
# Traceback (most recent call last):
# File /usr/lib/python3.9/code.py, line 15, in module
# next(g)
# StopIteration: Doneyield 表示 “产生”或“生成”produce。当程序执行到 yield 语句时就会 生产produce一个值即项目item而 next() 函数function就会在此暂停pauses there执行等待下一次调用。
当我们再次使用 next() 函数function对生成器对象generator object进行调用它会让生成器对象generator object从上一次暂停的位置继续执行直到遇到下一个 yield 语句或者执行结束。
普通函数normal functions 与 包含 yield 的函数functions including yield 的主要区别在于执行流程execution flow
普通函数按顺序执行executes sequentially并在遇到 return 语句statement或到达最后一行final line时返回结果。包括 yield 的函数会在调用 next() 时执行并在遇到 yield 语句时返回。再次调用 next() 时将从上次暂停的 yield 语句处继续执行。
有一个例子
def example():print(step 1)yield 1print(step 2)yield 2print(step 3)yield 3g example()next(g)
# step 1
# 1
next(g)
# step 2
# 2
next(g)
# step 3
# 3
next(g)
# Traceback (most recent call last):
# File /usr/lib/python3.9/code.py, line 21, in module
# next(g)
# StopIteration注包含 yield 语句的函数本身并不是生成器generator。它仍然是一个函数function但每次调用这个函数function时都可以返回一个生成器对象return a generator这个生成器对象的类型是class ‘generator’。生成器generator是一个类class而不是函数function。(正如我们之前所说生成器generator是迭代器Iterator的一个子类subclass。
next() 只能用于生成器generator类型。不能用于函数function。
def my_generator(maximum):n 0while n maximum:yield nreturn Doneprint(type(my_generator)) # class functionprint(type(my_generator(5))) # class generatorprint(my_generator(5)) # generator object my_generator at 0x10bc42ba0print(next(my_generator(5))) # 0print(next(my_generator))
# Traceback (most recent call last):
# File /usr/lib/python3.9/code.py, line 15, in module
# print(next(my_generator))
# TypeError: function object is not an iterator更多Generator应用实例
到目前为止我们知道生成器generators可以帮助我们保存生成项目items的算法并在需要时生成项目items。与包含所有项目items的庞大列表list相比生成器可以减少时间和内存成本。
表示无限的数据流infinite stream of data
事实上生成器generator甚至可以表示无限的数据流infinite stream of data。例如
def fibonacci():x, y 0, 1while True:x, y y, x yyield xfib fibonacci()
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))
# ...fib 是一个无限生成器infinite generator我们可以根据自己的需要使用它。
将多个生成器generators组成管道pipeline
生成器generators的另一个有趣应用interesting application是我们可以将一系列生成器generators组合起来得到一个新的生成器generator这在技术technically上被称为 “管道pipeline”。
def times_two(nums):for n in nums:yield n * 2def natural_number(maximum):x 0while x maximum:yield xx 1p times_two(natural_number(10))
print(type(p)) # class generator
print(next(p)) # 0
print(next(p)) # 2
print(next(p)) # 4
print(next(p)) # 6
print(next(p)) # 8
print(next(p)) # 10
print(next(p)) # 12
# ...如上例所示我们可以使用现有的两个生成器generators来定义一个新的生成器generator。这不是很好吗
Conclusion 结论
生成器Generator是 Python 中一种非常有用的机制useful mechanism可以减少时间reduce time和内存开销memory costs。它保存的是产生项item的算法algorithm而不是项items。我们还可以使用生成器generators生成produce无限的数据流infinite data stream和管道pipelines。