1. 什么是迭代?
迭代是程序中常见的操作,它指的是重复执行某一操作直到满足某个条件为止。Python中,我们可以通过for循环实现迭代。
1.1 for循环实现迭代
Python中,for循环是常用的一种迭代方法。它可以遍历任何可迭代对象,如字符串、列表、元组、字典等。
下面是一个遍历列表的例子:
fruits = ['apple', 'banana', 'orange']
for fruit in fruits:
print(fruit)
运行上面的代码,会输出:
apple
banana
orange
我们可以看到,for循环遍历了列表fruits中的所有元素,并输出了每个元素的值。
在for循环中,我们需要定义一个变量来接收可迭代对象中的每个元素。在上面的例子中,我们定义了变量fruit来接收fruits列表中的每个元素。
值得注意的是,在遍历字典时,for循环默认遍历字典的键。如果我们需要遍历字典的值,可以使用values()方法;如果我们需要同时遍历字典的键和值,可以使用items()方法。
1.2 while循环实现迭代
除了for循环,我们还可以使用while循环实现迭代。
下面是一个使用while循环遍历列表的例子:
fruits = ['apple', 'banana', 'orange']
i = 0
while i < len(fruits):
print(fruits[i])
i += 1
运行上面的代码,会输出:
apple
banana
orange
在上面的例子中,我们通过一个变量i来表示列表fruits中的元素的索引。通过while循环不断遍历列表,并输出每个元素的值,直到遍历完整个列表为止。
2. 可迭代对象和迭代器
在Python中,迭代的实现离不开两个核心概念:可迭代对象和迭代器。
2.1 可迭代对象
可迭代对象是指实现了__iter__()方法的对象。如列表、元组、字典等。
下面是一个实现了__iter__()方法的自定义类:
class MyIterable:
def __init__(self):
self.data = [1, 2, 3, 4, 5]
def __iter__(self):
return iter(self.data)
我们可以通过内置函数iter()来判断一个对象是否是可迭代对象。如果一个对象是可迭代对象,那么调用iter()函数会返回一个迭代器对象。
my_iterable = MyIterable()
if iter(my_iterable) is my_iterable:
print('my_iterable is iterable')
else:
print('my_iterable is not iterable')
运行上面的代码,会输出:
my_iterable is iterable
2.2 迭代器
迭代器是指实现了__next__()方法的对象。它可以不断返回下一个元素,直到没有元素为止。
下面是一个实现了__next__()方法的自定义迭代器:
class MyIterator:
def __init__(self, data):
self.data = data
self.idx = 0
def __iter__(self):
return self
def __next__(self):
if self.idx < len(self.data):
val = self.data[self.idx]
self.idx += 1
return val
else:
raise StopIteration()
我们可以通过内置函数next()来获取迭代器中的下一个元素。如果已经到达了迭代器的末尾,那么会抛出StopIteration异常。
my_iterable = MyIterable()
my_iterator = MyIterator(my_iterable)
for val in my_iterator:
print(val)
运行上面的代码,会输出:
1
2
3
4
5
值得注意的是,可迭代对象每次迭代都会返回一个新的迭代器对象。而且,同一个可迭代对象可以被多个迭代器同时遍历。
3. 生成器
生成器是Python中一种强大的迭代器,它可以通过一些特殊的语法来快速定义迭代器。
3.1 生成器表达式
生成器表达式是Python中创建生成器的一种简单方法。它类似于列表推导式,但是使用圆括号而不是方括号。
下面是一个使用生成器表达式创建生成器的例子:
my_generator = (x * x for x in range(5))
for val in my_generator:
print(val)
运行上面的代码,会输出:
0
1
4
9
16
在上面的例子中,我们使用生成器表达式创建了一个生成器my_generator。这个生成器可以依次返回0、1、4、9、16这些数的平方。
和列表推导式一样,生成器表达式也可以嵌套。下面是一个使用嵌套的生成器表达式创建生成器的例子:
my_generator = (x * y for x in range(3) for y in range(5))
for val in my_generator:
print(val)
运行上面的代码,会输出:
0
0
0
0
0
1
2
3
4
0
2
4
6
8
3.2 生成器函数
生成器函数是Python中定义生成器的另一种方法。它和普通函数的区别在于,生成器函数中使用yield语句来返回值,而不是使用return语句。
下面是一个使用生成器函数创建生成器的例子:
def my_generator():
for i in range(5):
yield i * i
gen = my_generator()
for val in gen:
print(val)
运行上面的代码,会输出:
0
1
4
9
16
在上面的例子中,我们定义了一个生成器函数my_generator()。它会依次返回0、1、4、9、16这些数的平方。我们可以通过调用生成器函数来创建一个生成器gen,然后使用for循环遍历这个生成器并输出值。
4. yield和yield from关键字
yield是Python中一个非常重要的关键字,它在生成器函数中用来返回值,并且暂停函数的执行,直到下一次调用生成器的__next__()方法时再继续执行。
4.1 yield关键字
下面是一个使用yield关键字的例子:
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
print(next(gen))
print(next(gen))
print(next(gen))
运行上面的代码,会输出:
1
2
3
在上面的例子中,我们定义了一个生成器函数my_generator()。它依次使用yield关键字返回了三个值,即1、2、3。我们可以通过调用生成器函数来创建一个生成器gen,然后使用next()函数(或者__next__()方法)来逐个输出这些值。
4.2 yield from关键字
Python3.3中,新增了yield from关键字,可以用来简化生成器函数的编写。
下面是一个使用yield from关键字的例子:
def sub_generator():
yield 1
yield 2
def my_generator():
yield from sub_generator()
yield 3
gen = my_generator()
print(next(gen))
print(next(gen))
print(next(gen))
运行上面的代码,会输出:
1
2
3
在上面的例子中,我们定义了两个生成器函数:sub_generator()和my_generator()。其中,sub_generator()会依次返回1、2两个值,而my_generator()会先调用sub_generator(),然后再返回一个值3。
我们可以通过在my_generator()中使用yield from关键字来将sub_generator()中的值依次传递给my_generator()中的生成器。