介绍
在本实验中,我们将学习 Python 的内置迭代器(Iterators)、生成器(Generators)和生成器表达式(Generator Expressions)。我们将了解如何使用这些结构来编写高效且优雅的 Python 代码。
学习目标
- 迭代器(Iterator)
- 生成器(Generator)
- 生成器表达式(Generator Expression)
在本实验中,我们将学习 Python 的内置迭代器(Iterators)、生成器(Generators)和生成器表达式(Generator Expressions)。我们将了解如何使用这些结构来编写高效且优雅的 Python 代码。
迭代器是一个可以被迭代(循环)的对象。它会逐个返回数据元素。在 Python 中,迭代器是从可迭代对象(如列表、元组或字符串)创建的。
打开一个新的 Python 解释器。
python3
要在 Python 中创建一个迭代器,我们需要在对象中实现两个方法:__iter__
和 __next__
。
__iter__
返回迭代器对象本身。__next__
方法返回迭代器中的下一个值。如果没有更多的元素可以返回,它应该抛出 StopIteration
异常。
以下是一个简单的迭代器示例,它遍历一个数字列表:
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
## len() 是列表中元素的数量
if self.index >= len(self.data):
raise StopIteration
result = self.data[self.index]
self.index += 1
return result
iterator = MyIterator([1, 2, 3, 4, 5])
for x in iterator:
print(x)
输出:
1
2
3
4
5
迭代器的有用之处在于它们允许我们逐个访问可迭代对象的元素,而不是一次性将所有元素加载到内存中。这在处理无法完全放入内存的大型数据集时尤其有用。
迭代器还用于在 Python 中实现惰性求值(lazy evaluation)。这意味着迭代器的元素只在需要时生成,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。
如果你想从迭代器中逐个获取元素,可以使用 next()
函数。该函数将返回迭代器中的下一个元素。如果没有更多元素,它将抛出 StopIteration
异常。
iterator = MyIterator([1, 2, 3, 4, 5])
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
## StopIteration
print(next(iterator))
输出:
1
2
3
4
## StopIteration
以下是 Python 中迭代器的一些常见用例:
生成器是一种使用函数创建的特殊类型的迭代器。它是一种使用函数创建迭代器的简单方法。
生成器函数的定义与普通函数类似,但它使用 yield
关键字而不是 return
关键字来返回值。当调用生成器函数时,它不会立即执行函数体,而是返回一个生成器对象,该对象可以用于按需执行函数体。
生成器函数可以在其函数体中的任何位置包含 yield
语句。当调用生成器函数时,它不会立即执行函数体,而是返回一个生成器对象,该对象可以用于按需执行函数体。
以下是一个生成器函数的示例,它生成一个数字列表的平方:
def my_generator(data):
for x in data:
yield x**2
for x in my_generator([1, 2, 3, 4, 5]):
print(x)
输出:
1
4
9
16
25
生成器的有用之处在于它们允许我们按需生成元素,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。
生成器还用于在 Python 中实现惰性求值(lazy evaluation)。这意味着生成器的元素只在需要时生成,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。
以下是 Python 中生成器的一些常见用例:
迭代器和生成器的主要区别在于它们的实现方式。
迭代器是一个实现了两个方法的对象:__iter__
和 __next__
。__iter__
方法返回迭代器对象本身,而 __next__
方法返回迭代器中的下一个值。
生成器是一个使用 yield
关键字返回值的函数。当调用生成器函数时,它不会立即执行函数体,而是返回一个生成器对象,该对象可以用于按需执行函数体。
以下是迭代器和生成器的主要区别总结:
__iter__
和 __next__
方法的对象。它们是从可迭代对象(如列表、元组或字符串)创建的。yield
关键字返回值的函数。它们通过调用生成器函数创建。总的来说,迭代器和生成器都是 Python 中用于遍历元素序列的有用工具。它们允许我们逐个访问或生成序列中的元素,这可能比一次性生成所有元素更高效。
在这个示例中,我们将创建一个生成质数的生成器。
首先,我们定义一个辅助函数 _is_prime
,如果数字是质数则返回 True
,否则返回 False
:
def _is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
现在,我们定义生成器函数 prime_numbers
:
def prime_numbers(n):
for i in range(2, n+1):
if _is_prime(i):
yield i
让我们测试一下这个生成器:
for prime in prime_numbers(20):
print(prime)
输出:
2
3
5
7
11
13
17
19
生成器表达式类似于列表推导式(list comprehension),但它返回的是一个生成器对象,而不是列表。
生成器表达式使用圆括号 ()
定义,可以包含一个或多个 for
子句。它是按需求值的,并返回一个生成器对象,该对象可以用于按需生成表达式中的元素。
以下是一个生成器表达式的示例,它生成一个数字列表的平方:
generator = (x**2 for x in [1, 2, 3, 4, 5])
for x in generator:
print(x)
输出:
1
4
9
16
25
生成器表达式的有用之处在于它们允许我们按需生成元素,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。
生成器表达式还用于在 Python 中实现惰性求值(lazy evaluation)。这意味着生成器表达式的元素只在需要时生成,而不是一次性生成所有元素。这可能是一种更高效的方法,因为它允许我们避免生成和存储不必要的元素。
以下是 Python 中生成器表达式的一些常见用例:
生成器表达式是 Python 中的强大工具,可用于编写高效且优雅的代码。
以下是一个列表推导式和一个生成器表达式的示例,它们生成一个数字列表的平方:
## 列表推导式
squares = [x**2 for x in [1, 2, 3, 4, 5]]
print(squares)
## 生成器表达式
squares_generator = (x**2 for x in [1, 2, 3, 4, 5])
for x in squares_generator:
print(x)
输出:
[1, 4, 9, 16, 25]
1
4
9
16
25
列表推导式和生成器表达式之间有几个相似之处和不同之处:
for
子句以及一个生成元素的表达式。总的来说,列表推导式和生成器表达式都是 Python 中生成元素序列的有用工具。列表推导式通常更快且占用更多内存,而生成器表达式通常较慢且占用更少内存。选择使用哪种方式取决于应用程序的具体需求。
在本实验中,我们学习了 Python 内置的迭代器(Iterators)、生成器(Generators)和生成器表达式(Generator Expressions)。我们了解了如何使用这些结构来编写高效且优雅的 Python 代码。我们还通过一个示例展示了如何使用生成器来实现一个质数生成器。