今天为大家解读python中的for循环,深入探讨它们在底层是如何开展工作的,以及他们为什么会按照自己的方式工作,他们与别的语言中的for循环有什么不同等问题。
![e81f15fd4e9844864641d1342bf6967a.png](https://i-blog.csdnimg.cn/blog_migrate/484ec41a45920d9ebd274ca94661a8f2.jpeg)
循环的问题
我们将通过看一些“陷阱”开始我们的旅程,在我们了解循环如何在 Python 中工作之后,我们将再次看看这些问题并解释发生了什么。
问题 1:循环两次
假设我们有一个数字列表和一个生成器,生成器会返回这些数字的平方:
>>> numbers = [1, 2, 3, 5, 7]>>> squares = (n**2 for n in numbers)
我们可以将生成器对象传递给 tuple 构造器,从而使其变为一个元组:
>>> tuple(squares)(1, 4, 9, 25, 49)
如果我们使用相同的生成器对象并将其传给 sum 函数,我们可能会期望得到这些数的和,即 88。
>>> sum(squares)0
但是我们得到了 0。
问题 2:包含的检查
让我们使用相同的数字列表和相同的生成器对象
>>> numbers = [1, 2, 3, 5, 7]>>> squares = (n**2 for n in numbers)
如果我们询问 9 是否在 squares 生成器中,Python 将会告诉我们 9 在 squares 中。但是如果我们再次询问相同的问题,Python 会告诉我们 9 不在 squares 中。
>>> 9 in squaresTrue>>> 9 in squaresFalse
我们询问相同的问题两次,Python 给了两个不同的答案。
问题 3 :拆包
这个字典有两个键值对:
>>> counts = {'apples': 2, 'oranges': 1}
让我们使用多个变量来对这个字典进行拆包:
>>> x, y = counts
你可能会期望当我们对这个字典进行拆包时,我们会得到键值对或者得到一个错误。
但是解包字典不会引发错误,也不会返回键值对。当你解包一个字典时,你会得到键:
>>> x'apples'
回顾:Python 的 for 循环
在我们了解一些关于这些 Python 片段的逻辑之后,我们将回到这些问题。
Python 没有传统的 for 循环。为了解释我的意思,让我们看一看另一种编程语言的 for 循环。
这是一种传统 C 风格的 for 循环,用 JavaScript 编写:
let numbers = [1, 2, 3, 5, 7];for (let i = 0; i < numbers.length; i += 1) {print(numbers[i])}
JavaScript、 C、 C++、 Java、 PHP 和一大堆其他编程语言都有这种风格的 for 循环,但是 Python 确实没有。
Python 确实没有 传统 C 风格的 for 循环。在 Python 中确实有一些我们称之为 for 循环的东西,但是它的工作方式类似于 foreach 循环。
这是 Python 的 for 循环的风格:
numbers = [1, 2, 3, 5, 7]for n in numbers:print(n)
与传统 C 风格的 for 循环不同,Python 的 for 循环没有索引变量,没有索引变量初始化,边界检查,或者索引递增。Python 的 for 循环完成了对我们的 numbers 列表进行遍历的所有工作。
因此,当我们在 Python 中确实有 for 循环时,我们没有传统 C 风格的 for 循环。我们称之为 for 循环的东西的工作机制与之相比有很大的不同。
定义:可迭代和序列
既然我们已经解决了 Python 世界中无索引的 for 循环,那么让我们在此之外来看一些定义。
可迭代是任何你可以用 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 也有许多其他种类的迭代器。
Python 的 for 循环不使用索引
你可能认为,Python 的 for 循环在底层使用了索引进行循环。在这里我们使用 while 循环和索引手动遍历:
numbers = [1, 2, 3, 5, 7]i = 0while 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 "