Python基础之 生成器|Python 主题月

844 阅读4分钟

1. 生成器

本文正在参加「Python主题月」,详情查看活动链接

首先让我们了解迭代器。迭代器是一个对象,它使程序员能够遍历容器,尤其是列表。但是,迭代器执行遍历并访问容器中的数据元素,但不执行迭代。你可能会感到困惑,所以让我们慢慢来。分为三个部分,分别是:

  • 可迭代的
  • 迭代器
  • 迭代

所有这些部分都相互关联。我们将一一讨论它们,稍后再讨论生成器。

1.1 可迭代的

iterable是 Python 中的任何对象,它定义了一个__iter__或一个__getitem__方法,该 方法返回一个迭代器或可以采用索引。简而言之, iterable是任何可以为我们提供迭代器的对象。那么什么是迭代器

1.2 迭代器

迭代器是 Python 中定义了next(Python2) 或 __next__方法的任何对象。就是这样。那是一个迭代器。现在让我们了解迭代

1.3 迭代

迭代,它是从某事物(例如列表)中获取数据的过程。当我们使用循环来循环某些东西时,它被称为迭代。它是进程本身的名称。现在我们对这些术语有了基本的了解,让我们来了解generators

1.4 生成器

生成器是迭代器,但你只能迭代它们一次。这是因为它们不会将所有值都存储在内存中,而是即时生成值。可以通过迭代它们来使用它们,或者使用“for”循环,或者通过将它们传递给任何迭代的函数或构造。大多数时候generators都是作为函数来实现的。然而,他们没有return,它们是用yield。下面是一个简单的generator函数示例:

def generator_function():
    for i in range(10):
        yield i

for item in generator_function():
    print(item)

# Output: 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9

在这种情况下它不是很有用。生成器最适合计算大量结果(特别是涉及循环本身的计算),您不想同时为所有结果分配内存。

下面是一个generator计算斐波那契数的例子:

def fib(n):
    a = b = 1
    for i in range(n):
        yield a
        a, b = b, a + b

现在我们可以这样使用它:

for x in fib(1000000):
    print(x)

这样我们就不必担心它会使用大量资源。但是,如果我们像这样实现它:

def fib(n):
    a = b = 1
    result = []
    for i in range(n):
        result.append(a)
        a, b = b, a + b
    return result

在计算大量输入时,它会耗尽我们所有的资源。我们已经讨论过我们只能迭代generators一次,但我们还没有对其进行测试。在测试之前,您需要了解 Python 的另一个内置函数next(). 它允许我们访问序列的下一个元素。那么让我们测试一下我们的理解:

def generator_function():
    for i in range(3):
        yield i

gen = generator_function()
print(next(gen))  # 每执行一次next()返回一个结果,
# Output: 0
print(next(gen))
# Output: 1
print(next(gen))
# Output: 2
print(next(gen))
# Output: Traceback (most recent call last):
#            File "<stdin>", line 1, in <module>
#         StopIteration

正如我们所看到的,在产生所有值后next()导致 StopIteration错误。基本上这个错误告诉我们所有的值都已经产生。您可能想知道为什么在使用for循环时我们不会收到此错误?答案很简单。该 for循环自动捕获这个错误并停止通话 next。您知道 Python 中的一些内置数据类型也支持迭代吗?让我们来看看:

string = "Yasoob"
next(string)
# Output: Traceback (most recent call last):
#      File "<stdin>", line 1, in <module>
#    TypeError: str object is not an iterator

嗯,这不是我们所期望的。错误说这str不是迭代器。嗯,没错!它是一个可迭代但不是迭代器。这意味着它支持迭代,但我们不能直接对其进行迭代。那么我们将如何迭代它呢?是时候了解另一个内置函数iteriterator从可迭代对象返回一个对象。我们可以在字符串上使用它!

var = 1779
iter(var)
# Output: Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: 'int' object is not iterable
# This is because int is not iterable

my_string = "YDAZHUANG"
my_iter = iter(my_string)  # 看出转换为生成器 iter(可迭代)
print(next(my_iter))
# Output: 'Y'