我个人看到的理解python“迭代”概念最好的一篇文章

深入理解python迭代

原文:
更深入的理解 Python 中的迭代
作者: Trey Hunner 译者:LCTT MjSeven

1本文内容说明

2本文的python运行环境说明

一、什么是迭代
    (斜体字内容来自百度百科)迭代,就是重复反馈的活动,目的通常是为了逼近所需的目标,每一次重复成为一次迭代。每一次迭代的结果都会作为下一次的初始值。
    对计算机特定程序中需要反复执行的子程序,进行一次重复,即重复执行程序中的循环,直到满足某种条件为止,亦称为迭代。

    我的理解:python中的迭代,按上面的定义,需要反复执行的子程序就是next(),满足的条件就是StopIteration这个TypeError产生。

二、python中的for循环
    python中,没有用索引形成的for循环,例如:

for (i = 0, i < = 10, i++)

    python中的循环,是for each in形式的循环:

for number in numbers:

三、可迭代和序列

  • python中的序列,包括列表(list)、元组(tuple)和字符串(string);
  • 迭代意味着循环,可迭代意味着可循环可遍历,反之,可循环可遍历意味着可迭代;
  • 所有python中的序列,都是可遍历的,也就是可迭代的;
  • python中,除了序列外,字典、集合、文件以及生成器,都是可迭代的。

四、迭代器
    “迭代器”就是可以驱动“可迭代对象”的“东西”。python中,可以使用iter()函数获取“”可迭代对象的“迭代器”
    一旦获得“迭代器”,就可以将它传递给内置的next()函数,获取它的下一项。

"""首先定义一个numbers列表,然后通过生成器表达式
生成一个生成器对象squares"""
>>> numbers = [1, 2, 3. 4. 5]
>>> squares = (number ** 2 for number in numbers)
#my_iter是生成器squares的迭代器
#由iter函数生成
>>> my_iter = iter(squares)
>>> my_iter
>>> <list_iterator object at 0x10a9ba208>
#next函数返回迭代器my_iter的下一项
>>> next(my_iter)
1
>>> next(my_iter)
4
>>> next(my_iter)
9
>>>

    迭代器是有“状态的”,一旦消耗了一项,它就会“消失”,也就是说,每调用一次迭代器,就消耗一个迭代器,直到产生一个StopIteration异常

>>> next(my_iter)
16
>>> next(my_iter)
25
>>> next(my_iter)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>

再看下面这个例子:

>>> numbers = [1, 2, 3, 4, 5]
>>> squares = (number ** 2 for number in numbers)
>>> next(squares)
1
>>> next(squares)
4
>>> for number in squares:
...     print(number)
... 
9
16
25
>>> 

为什么结果是这样?for循环只输出了9、16和25?
因为在第3行和第5行,两次next函数调用,使得squares的迭代器(因为squares是生成器,而生成器本身也是迭代器)“消失了”2个,只剩下了后面的3个。
    结合上面对“可迭代对象”及“迭代器”的讨论,可以对python的for循环作如下理解:

Created with Raphaël 2.2.0 开始 从给定的可迭代对象获得迭代器 反复从迭代器中获取下一项 是否得到一个StopIteration异常? 结束 yes no

    下面这段代码“定义”了python的for:

def funky_loop(iterable, action_todo):
	iterator = iter(iterable)
	done_looping = False
	while not done_looping:
		try:
			item = next(iterator)
		except StopIteration:
			done_looping = True
		else:
			action_todo(item)

五、迭代器协议
    迭代器协议(Iterator Protocol),定义了iter和next如何工作,python中所有形式的迭代都是由迭代器协议驱动的。
    “生成器”本身就是迭代器(可以用next获取下一项),也可以用for循环遍历,这就引出一个概念:迭代器是可迭代的,当我们在迭代器上使用iter时,iter返回迭代器自己,但迭代器与可迭代对象不同的是:迭代器对象没有长度,不能被索引。

"""next()"""
>>> numbers = [1, 2, 3, 4, 5]
>>> squares = (number **2 for number in numbers)
>>> next(squares)
1
>>> next(squares)
4
>>> next(squares)
9

"""for"""
>>> numbers = [1, 2, 3, 4, 5]
>>> squares = (number **2 for number in numbers)
>>> for square in squares:
...     print(square)
... 
1
4
9
16
25
>>>

"""len"""
>>> len(squares)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()
>>> my_iter = iter(squares)
>>> len(my_iter)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'generator' has no len()
>>>
对象 可迭代 迭代器
可迭代对象 不一定
迭代器
生成器
列表

python迭代器协议总结

  • 可迭代对象传给iter函数,获得迭代器;
  • 迭代器:
    • 可传递给next函数,它将给出下一项,如果没有下一项,给出StopIteration异常;
    • 可传递给iter函数,返回自身的一个迭代器
  • 这些语句反过来也是正确的:
    • 任何可以在不引发TypeError异常的情况下传递给iter的东西都是可迭代的;
    • 任何可以在不引发TypeError异常的情况下传递给next的东西都是一个迭代器
    • 当传递给iter时,任何返回自身的东西都是一个迭代器

  1. 本文是我阅读原文后的笔记和心得。感谢原文作者。 ↩︎

  2. Python 3.7.1 [Clang 6.0 (clang-600.0.57)] on darwin ↩︎

猜你喜欢

转载自blog.csdn.net/steventian72/article/details/85487276