13 KiB
Python range()函数:示例操作指南
Python range()函数可用于创建数字序列。range()函数可以被迭代,并且在与 for 循环结合时是理想的。本文将仔细研究 Python 范围函数:
- 这是什么?
- 如何使用 range()
- 如何用 range()函数创建 for 循环
我还将向您展示如何在 for 循环中使用范围来创建您想要的任何类型的循环,包括:
- 数量范围不断增加的常规循环
- 向后循环(例如从 10 到 0)
- 跳过值的循环
目录
什么是 Python range 函数?
Python 的range作为内置函数,通常用于在 for-loops 中循环特定次数。像 Python 中的许多东西一样,它实际上是一个 Python 类型(或类),但当在循环中使用它时,我们可以将其视为一个返回 iterable 对象的内置函数。
Range 根据我们的输入为我们提供了一个经过计算的数字序列。有三种方法可以调用 range 函数:
# With one integer argument it
# counts from 0 to stop
range(stop)
# With two integer arguments it
# counts from start to stop
range(start, stop)
# With three integer arguments it
# counts from start to stop,
# with a defined step size
range(start, stop, step)
参数 start、stop 和 step 总是整数。当我们调用 range 时,它返回一个类的对象range。这个 range 对象可以反过来提供一个 Python 迭代器,这意味着我们可以循环(迭代)它的值。范围迭代器在每次调用时都会计算一个新值。该值基于开始、停止和步长值。
如果这听起来很难:的确很难。如果您不完全理解迭代器和可迭代性,此时您有两个选择:
- 继续阅读,看看如何使用范围。我不会怪你。
- 首先阅读迭代器和可迭代对象,然后回到这里。
如果你想学习 Python,我建议你帮自己一个忙,选择第二个选项。
如何使用 Python 范围
使用范围有三种方式。我们将从最简单的用例开始,详细研究这三个方面。为了让您彻底理解 Python range 函数,稍后我将向您展示 range 在内部是如何工作的;其实挺简单的!然而,最好先看看如何使用范围的例子,这样你就能更好地了解它们是什么以及它们能做什么。
只有停止值的范围
如果我们用一个参数调用range,这个参数就是停止值。在这种情况下,range将从 0 开始计数,直到达到停止值。
例如,如果我们调用range(5),当我们迭代它时,创建的 range 对象将返回值 0、1、2、3 和 4。所以,重要注意: range 一到达止损值就停止,不会返回止损值本身。
如果这听起来令人困惑,一个简单的例子将有望澄清它。让我们在 for 循环中使用range调用:
https://crumb . sh/embed/3ksrw 4 kt ky
为什么 range 不包括结束值?
你可能想知道为什么range不包括结束值。这一切都归结到一个重要的原则,称为零基索引。计算机从零开始计数,而人类从 1 开始计数。当计算机需要给 3 个元素编号时,它从元素 0 开始,然后是 1,然后是 2。索引也是一样。当访问 Python 列表中的元素时,第一个元素驻留在位置 0。我们可以这样访问它:my_list[0]。
由于这种从零开始的索引,如果 Python 范围也从零开始计数就容易多了。例如,如果你想使用一个范围来遍历一些东西,你可能会想从元素 0 开始。
带起始值和终止值的范围
我们并不总是希望从零开始计数,这就是为什么我们也可以用起始值和终止值来调用 range。对 range(2,5)的调用将返回值 2、3 和 4。这是另一个例子:
https://crumb.sh/embed/ukfdzkeqogo
步长为正值的范围
最后,range()采用一个可选参数,称为步长。步长定义了计算出的数字之间的步长。最好只说明这一点:
for i in range(0, 6, 2):
print(i, end=" ")
# Output will be: 0 2 4
每一步跳过一个数字,因为步长是 2。让我们增加步长:
for i in range(0, 101, 10):
print(i, end=" ")
# Output will be:
# 0 10 20 30 40 50 60 70 80 90 100
因为我们将stop设置为 101,所以值 100 也包含在这个范围内。
负步长范围
范围也可以倒计数。如果我们将步长设置为负数,范围将向后计数。如果我们想倒计数,我们需要确保start的值比end的值大*。这里有一个例子:*
for i in range(5, 0, -1):
print(i, end=" ")
# Output will be:
# 5 4 3 2 1
我们从 5 开始倒数到 0。因为范围不包括结束值本身,所以不包括 0。如果要包含 0,需要将end设置为-1。
Python 范围如何工作
现在,您已经看到了 range 的作用,我将告诉您 range 如何在内部工作,以便更好地理解它们。实际上,它没有多少魔力!
Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these free articles, I hope you understand! Support me by disabling your adblocker on my website or, alternatively, buy me some coffee. It's much appreciated and allows me to keep working on this site!
范围是一个可迭代的对象,这个对象可以返回一个迭代器来跟踪它的当前状态。假设我们用调用range(3)创建一个范围。这将返回一个具有我们所请求的设置的 range 类型的对象。在内部,Python 范围将设置以下内部变量:
- 起始值为 0,
- 结束值为 3,
- 并将步长值设置为默认值 1。
当我们开始迭代一个 range 对象时,range 对象将返回一个迭代器。这个迭代器使用上面定义的值,但是有一个额外的值:一个计数器变量i,默认情况下初始化为 0,并在每次迭代中增加。
每次调用迭代器来获取下一个数字时,range 都会查看其内部状态,并计算要返回的下一个数字。下一个值是这样计算的:
next = start + step*i。
默认情况下,范围的步长为 1:
- 所以在第一次调用时,进行的计算是这样的:
0 + 1*0 == 0。Range 返回 0,计数器i加 1,使i == 1 - 在第二次调用时,它使用其当前状态进行相同的计算:
0 + 1*1 = 1。它再次将计数器i增加到 2。 - 第三次调用返回 2,因为
0 + 1*2 == 2。 - 我们现在已经到达了范围的尽头。正如我在关于 Python 迭代器的文章中所解释的,对迭代器的任何后续调用都将返回一个
StopIteration异常,表明不再有条目。
如果用range(0, 5, 2)给你的范围一个步长 2,你可以重复上面的计算,看到返回值现在是:0 和 2。
用代码演示
我们可以用一些代码来演示这个过程。在下面的例子中,我们首先创建一个 range 对象。接下来,我们使用内置的iter()函数从 range 对象手动请求一个迭代器。我们开始使用另一个内置函数从它那里请求下一个值:next()。在 3 次调用之后,您看到 iterable 被耗尽,并开始引发StopIteration异常:
my_range = range(0, 3)
# Obtain the iterable. In a loop, this manual
# step is not needed
my_iter = iter(my_range)
# Request values from the iterable
print(next(my_iter))
# 0
print(next(my_iter))
# 1
print(next(my_iter))
# 2
print(next(my_iter))
# throws a StopIteration exception
如果您愿意,您也可以自己运行这段代码:
https://crumb . sh/embed/C4 dmggj 56 qev
Python 范围:Iterable 还是 iterator?
range 对象是可迭代的,这意味着它是一个可以返回迭代器的对象。正如你在上面的例子中看到的,我们可以用 iter()函数手动获得这个迭代器。在 for 循环中使用时,循环会自动请求迭代器,一切都会得到处理。
range 对象(iterable)将在每次调用时返回一个新的迭代器。因此,尽管这不是我们通常使用范围的方式,但我们实际上可以通过向 range 对象请求新的迭代器来继续使用它。如果你想详细理解这一点,请阅读 iterables 和 iterators 。
Python 范围 vs 列表
与列表相比,范围提供了一个很大的优势:它们需要一个恒定的、可预测的内存量,因为它们是动态计算的。一个范围需要跟踪的只是开始、停止、结束和迭代计数器。因此范围(1000)需要与范围(1)相同的内存量。
相比之下:值为 0 到 999 的列表比只有值 1 的列表占用的内存多一千倍。
在 Python 2 中,情况并非如此。常规范围将具体化为一个实际的数字列表。在某个时候,xrange 被引入。在 Python 3 中,xrange 将成为范围的缺省值,旧的物化范围被丢弃了。此外,还增加了一些额外的特性,比如切片和比较范围的能力。
名称 xrange 在 Python 3 中不存在。如果您遇到它,您可能会看到 Python 2 代码。我写了一篇关于这个主题的文章,如果你想把它转换成 Python 3 代码的话。
实践中的 Python 范围
下面是一些常见的和不太常见的操作,除了在循环中使用它们之外,在实践中还可能用到。
将范围转换为列表
我们了解到范围是计算出来的,而列表是物化的。有时你想从一个范围中创建一个列表。你可以用 for 循环来实现。或者,更 Python 化更快:通过使用 Python 列表理解。然而,最好的方法是使用list()函数,它可以将任何可迭代对象转换成列表,包括范围:
my_list = list(range(0, 3))
print(my_list)
# [0, 1, 2]
成员资格测试
范围的行为类似于常规集合,因此我们也可以测试它们是否属于某个值。例如,要测试某个数字是否属于某个范围,您可以这样做:
my_number = 10
print(my_number in range(0, 11))
# True
范围切片
虽然我不确定你是否需要它(我从未在实践中使用过),但这是一个非常酷的特性。就像您可以分割列表和其他具有序列类型的对象一样,您也可以分割 range 对象。这样做时,您可能会期望范围被具体化为一个列表。事实并非如此。相反,会计算并返回一个新的 range 对象,正如您在以下关于 Python REPL 的示例中所看到的:
>>> range(0, 5)[2:4]
range(2, 4)
>>> range(0, 5)[4:2:-1]
range(4, 2, -1)
>>> range(0, 10)[2:8:2]
range(2, 8, 2)
比较范围
最后,范围也可以比较。比较范围时,它们作为序列进行比较。您可能希望 Python 只检查它们是否是同一个对象。在 Python 3.3 问世之前,情况一直如此。此后,产生相同序列的两个不同范围在 Python 中将被视为相等。
以下是 REPL 的一些例子:
>>> range(0, 2) == range(0, 3)
False
>>> range(0) == range(4, 2)
True
在最后一个例子中,开始为 4,结束为 2 的范围将导致长度为零的范围,因此它等于 a range(0)。
结论
您已经了解了 Python 的范围以及如何在 for 循环中使用它。不仅如此;您还了解了产品系列的内部运作方式。除了这些基础知识之外,您还学习了如何将一个范围转换为一个列表,范围可以进行比较,测试成员资格,我们甚至可以对范围进行切片。
如果您想了解更多关于产品系列的信息,您可能会对以下资源感兴趣:
- 我关于 Python 迭代器和可迭代性的文章
- 关于靶场的官方文件
- Trey Hunner 的这篇文章详细解释了为什么 range 不是迭代器(但它是可迭代的)*