深入理解 Python 中的循环和迭代

在Python中,可迭代对象就是可以用for来循环的东西。

for item in some_iterable:

print(item)

序列是一种非常常见的可迭代对象,例如列表、元组和字符串都是序列。

numbers = [1, 2, 3, 5, 7]

coordinates = (4, 5, 7)

words = “hello there”

序列是具有一组特定特征的可迭代对象,它们可以从0开始索引,并在比序列长度少一个元素的地方结束。它们有长度,并且可以切片。列表、元组、字符串和所有其他序列都是这样工作的。

numbers[0]

1

coordinates[2]

7

words[4]

‘o’

Python中的很多东西都是可迭代对象,但并非所有的可迭代对象都是序列。集合、字典、文件和生成器都是可迭代对象,但它们都不是序列。

my_set = {1, 2, 3}

my_dict = {‘k1’: ‘v1’, ‘k2’: ‘v2’}

my_file = open(‘some_file.txt’)

squares = (n**2 for n in my_set)

因此,任何可以用for来循环的东西都是一个可迭代对象,例如序列,但是并非所有可迭代对象都是序列。

Python的for循环


前面已经显示了,Python的for循环不使用索引——这是不同于C语言分割的for循环之处。

不过,你可能会悄悄滴认为,如果非要用,Python的for循环肯定也能实现C语言风格,因为我们一向认为“C语言是任何东西的基础”。为此,我们使用while 循环和索引手动遍历一个可迭代对象:

numbers = [1, 2, 3, 5, 7]

i = 0

while i < len(numbers):

print(numbers[i])

i += 1

很显然,上面的循环方式只适合于序列类对象,对其它的并非完全使用,比如字典、集合。

比如使用索引手动遍历一个集合,我们将看到报错:

fruits = {‘lemon’, ‘apple’, ‘orange’, ‘watermelon’}

i = 0

while i < len(fruits):

… print(fruits[i])

… i += 1

… Traceback (most recent call last): File “”, line 2, in

TypeError: ‘set’ object does not support indexing

集合不是序列,因此它们不支持索引。

在Python中,我们_不能_通过使用索引手动遍历每个可迭代对象。这对于不是序列的可迭代对象根本不起作用。

迭代器


在Python中,迭代器可以用于for循环。

什么是迭代器?它是驱动可迭代对象的一类对象。我们可以从任意可迭代对象那里生成迭代器。

这里有三个可迭代对象:集合、元组和字符串。

numbers = {1, 2, 3, 5, 7}

coordinates = (4, 5, 7)

words = “hello there”

可以用Python内置的iter函数用上面的可迭代对象生成迭代器。

iter(numbers)

<set_iterator object at 0x7f2b9271c860>

iter(coordinates)

<tuple_iterator object at 0x7f2b9271ce80>

iter(words)

<str_iterator object at 0x7f2b9271c860>

有了迭代器,就把它传给内置函数next,从而获得它的下一项。

numbers = [1, 2, 3]

my_iterator = iter(numbers)

next(my_iterator)

1

next(my_iterator)

2

每从迭代器中取出一项,那一项就从迭代器中“消失”了。如果到了迭代器的最后一项,还执行next,而实际上后面已经没有其他项了,这时候就会报出StopIteration异常。

next(iterator)

3

next(iterator)

Traceback (most recent call last): File “”, line 1,

in StopIteration

不用for的循环


在了解了迭代器、以及iternext函数后,我们将尝试手动遍历一个可迭代对象,而不使用for循环。

不用for,就得用while了,Python中只有这么两个循环语句。

def funky_for_loop(iterable, action_to_do):

for item in iterable:

action_to_do(item)

为了去掉for,需要:

  1. 根据给定的可迭代对象生成迭代器

  2. 从迭代器中重复获取下一项

  3. 如果成功获得了下一项,则相当于执行for循环了

  4. 如果在获取下一项时遇到“StopIteration”异常,则停止循环

def funky_for_loop(iterable, action_to_do):

iterator = iter(iterable)

done_looping = False

while not done_looping:

try:

item = next(iterator)

except StopIteration:

done_looping = True

else:

action_to_do(item)

这里,其实是用while循环和迭代器重新发明了for循环。

上面的代码基本上定义了Python中循环的工作方式。如果你了解内置的iternext函数在遍历对象时的工作方式,那么你就了解了Python的for循环是如何工作的,它们的工作过程是类似的。

实际上,通过上面的代码,不仅仅展示了for循环的工作原理,所有可迭代对象的循环都如此。

总结一下,迭代器协议是描述“Python中可迭代对象的循环如何工作的”的一种基本方式,它本质上是Python中iternext函数所定义的,Python中所有形式的迭代都由迭代器协议提供支持。

迭代器协议也被用于for

for n in numbers:

print(n)

多重赋值也使用迭代器协议:

x, y, z = coordinates

下面这种使用*的表达式也使用迭代器协议:

a, b, *rest = numbers print(*numbers)

许多内置函数依赖于迭代器协议:

unique_numbers = set(numbers)

Python中任何与可迭代对象一起工作的东西都可能以某种方式使用迭代器协议。在Python中,每当你遍历一个可迭代对象时,都依赖于迭代器协议。

生成器是迭代器


迭代器看起来很酷,不过,它是不是用途有限呢?或者说作为普通的Python编程者,是不是不需要关心它呢?

非也。

迭代器很常见。

numbers = [1, 2, 3]

squares = (n**2 for n in numbers)

此处得到的squares是一个生成器,生成器也是迭代器,这意味着你可以对生成器调用next,以获取其下一项:

next(squares)

1

next(squares)

4

for循环同样可以遍历生成器:

squares = (n**2 for n in numbers)

for n in squares:

… print(n)

… 1 4 9

下面这句话,貌似废话,但是重要:迭代器是可迭代对象

这就意味着,可以将迭代器对象作为iter函数的参数,生成一个新的迭代器对象。不是吗?

numbers = [1, 2, 3]

iterator1 = iter(numbers)

iterator2 = iter(iterator1) # 迭代器对象作为参数

以上最终得到的iterator2是一个迭代器。不过,要注意,iterator1iterator2的关系:

iterator1 is iterator2

True

iter函数的参数如果是一个迭代器,返回对象仍然是该迭代器对象自身。

结论:迭代器是可迭代对象,所有迭代器都是自己的迭代器。

def is_iterator(iterable):

return iter(iterable) is iterable

困惑了吗?

继续。

迭代器没有长度,因此无法索引。这个认识必须要建立起来。

numbers = [1, 2, 3, 5, 7]

iterator = iter(numbers)

len(iterator)

TypeError: object of type ‘list_iterator’ has no len()

iterator[0]

TypeError: ‘list_iterator’ object is not subscriptable

从Python程序员的角度来看,使用迭代器可以做的唯一有用的事情就是:将迭代器传给内置的next函数、或遍历迭代器:

next(iterator)

1

list(iterator)

[2, 3, 5, 7]

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img
img

二、Python必备开发工具

工具都帮大家整理好了,安装就可直接上手!img

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、Python视频合集

观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

五、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。img

六、面试宝典

在这里插入图片描述

在这里插入图片描述

简历模板在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值