使用 range() 以相反的顺序打印列表?
Posted
技术标签:
【中文标题】使用 range() 以相反的顺序打印列表?【英文标题】:Print a list in reverse order with range()? 【发布时间】:2011-11-09 07:47:49 【问题描述】:如何在 Python 中使用range()
生成以下列表?
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
【问题讨论】:
那么 [*range(9, -1, -1)] 呢?超级蟒蛇! 【参考方案1】:使用reversed()
函数:
reversed(range(10))
这更有意义。
更新:
如果你希望它是一个列表(正如 btk 指出的那样):
list(reversed(range(10)))
更新:
如果你只想使用range
来达到同样的效果,你可以使用它的所有参数。 range(start, stop, step)
例如,要生成列表[5,4,3,2,1,0]
,您可以使用以下内容:
range(5, -1, -1)
它可能不那么直观,但正如 cmets 所提到的,这更有效,并且可以正确使用反向列表的范围。
【讨论】:
虽然它“效率较低”。而且你不能对它进行切片操作。 这也会产生一个从 8 到 0 的列表,而不是从 9 到 0。 这将导致为整个范围分配内存,这对于大范围或您不需要所有值来说效率低下。 Python 2 中的range(9, -1, -1)
或 xrange(9, -1, -1)
会给你一个迭代器。
在 python 生成器中使用“reversed”(假设我们在谈论 Python 3 内置范围)在概念上是错误的,并且在使用高级语言进行编程时教导了不考虑内存/处理复杂性的错误习惯。
在 Python3 中,reversed
通常不接受生成器,但它接受 range
。为什么reversed(range(10000))
需要为整个列表分配内存? range
可以返回一个实现__reversed__
方法的对象,该方法允许有效的反向迭代?【参考方案2】:
使用“范围”内置函数。签名是range(start, stop, step)
。这将产生一个产生数字的序列,从start
开始,如果达到stop
则结束,不包括stop
。
>>> range(9,-1,-1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> range(-2, 6, 2)
[-2, 0, 2, 4]
在 Python 3 中,这会生成一个非列表 range
对象,其功能类似于只读列表(但使用的内存要少得多,尤其是对于大范围而言)。
【讨论】:
能否请您解释一下,也请您向我推荐任何有关python的网站/pdf书籍 @ramesh 如果你在 python shell 中运行help(range)
,它会告诉你参数。它们是开始的数字,结束的数字(不包括)和要采取的步骤,所以它从 9 开始并减去 1 直到它达到 -1(此时它停止而不返回,这就是为什么范围以 0 结束)
@ramesh.mimit:去 Python 官方网站就行了。那里有完整的文档,包括一个很棒的教程。
真的,这是正确的答案,但可以更清楚地解释。 range(start, stop, step)
-- 从数字start
开始,除非达到stop
,否则会产生结果,每次移动step
。【参考方案3】:
您可以使用range(10)[::-1]
,它与range(9, -1, -1)
相同,并且可以说更具可读性(如果您熟悉常见的sequence[::-1]
Python 习语)。
【讨论】:
【参考方案4】:对于那些对迄今为止收集的选项的“效率”感兴趣的人......
Jaime RGP's answer 引导我在定时按照我自己的建议(通过评论)Jason 的有点“具有挑战性”的解决方案之后重新启动我的计算机。为了让好奇的你免去停机时间,我在这里展示我的结果(最差优先):
Jason's answer(也许只是对list comprehension的力量的一次探索):
$ python -m timeit "[9-i for i in range(10)]"
1000000 loops, best of 3: 1.54 usec per loop
martineau's answer(如果您熟悉extended slices syntax,则可以阅读):
$ python -m timeit "range(10)[::-1]"
1000000 loops, best of 3: 0.743 usec per loop
Michał Šrajer's answer(已接受,可读性很强):
$ python -m timeit "reversed(range(10))"
1000000 loops, best of 3: 0.538 usec per loop
bene's answer(第一个但非常粗略的at that time):
$ python -m timeit "range(9,-1,-1)"
1000000 loops, best of 3: 0.401 usec per loop
使用range(n-1,-1,-1)
符号Val Neekman 很容易记住最后一个选项。
【讨论】:
我在阅读这个答案之前做了自己的计时,得到了相同的结果。 这些时间点很有用,但你还没有说出结论:时间差是如此微不足道,你应该使用最易读的那个,而不用担心它。事实上,可读性最强的 (reversed(...)
) 和最快/最不可读的 (range(9,-1,-1)
) 之间的差异大约是百万分之一秒。您的用户不会注意到 :-) 但会注意到代码可读性较差可能导致的错误。
忘了补充:它们在这种形式下也没什么用,因为当你迭代数百万个元素时,肯定会有更大的不同。 10 个元素太少,没有特别的意义。【参考方案5】:
使用reverse
没有意义,因为range
函数可以返回反向列表。
当您对 n 个项目进行迭代并想要替换 range(start, stop, step)
返回的列表顺序时,您必须使用标识 step
的范围的 第三个参数 和设置为-1
,其他参数相应调整:
-
提供
stop
参数为-1
(之前的值stop - 1
,stop
等于0
)。
作为启动参数使用n-1
。
所以相当于range(n)
的倒序是:
n = 10
print range(n-1,-1,-1)
#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
【讨论】:
坦率地说,我觉得这不如reversed(range(n))
直观
@NicholasHamilton 同意你的观点,但是这个答案背后的想法是使用更少的资源......(问题是关于使用范围函数:))
好的,不用担心,我想这取决于具体情况。例如,如果 range 函数被用作循环的索引,那么它的效果会很有限,但是,如果它在外部循环中使用,那么成本就会增加......【参考方案6】:
for i in range(8, 0, -1)
将解决这个问题。会输出8比1,-1表示倒序列表
【讨论】:
这将给出8, 7, ... 1
而不是8, 7, ... 0
。在某种程度上,这是一个很好的答案,因为它显示了 range(..., -1)
技术有多糟糕。【参考方案7】:
抛开可读性不谈,reversed(range(n))
似乎比 range(n)[::-1]
快。
$ python -m timeit "reversed(range(1000000000))"
1000000 loops, best of 3: 0.598 usec per loop
$ python -m timeit "range(1000000000)[::-1]"
1000000 loops, best of 3: 0.945 usec per loop
如果有人想知道:)
【讨论】:
很高兴有一些数字 :) -- 你为什么不加range(1000000000-1,-1,-1)
呢?
...最好不要在命令行上尝试timeit range(1000000000-1,-1,-1)
,而是查看my results :-)【参考方案8】:
经常被问到的问题是range(9, -1, -1)
在 Python 3 中是否比 reversed(range(10))
更好?在其他语言中使用过迭代器的人会立即倾向于认为 reversed() 必须缓存所有值,然后以相反的顺序返回。问题是如果对象只是一个迭代器,Python 的 reversed()
运算符就不起作用。要使 reversed() 工作,该对象必须具有以下两个之一:
-
通过
[]
支持len()
和整数索引
或者实现__reversed__()
方法。
如果您尝试在没有上述任何一项的对象上使用 reversed(),那么您将得到:
>>> [reversed((x for x in range(10)))]
TypeError: 'generator' object is not reversible
简而言之,Python 的reversed()
仅适用于类似数组的对象,因此它应该具有与前向迭代相同的性能。
但是range()
呢?不是发电机吗?在 Python 3 中,它是生成器,但包装在实现上述两者的类中。所以range(100000)
不会占用大量内存,但它仍然支持高效的索引和反转。
因此,总而言之,您可以使用 reversed(range(10))
而不会影响性能。
【讨论】:
【参考方案9】:此问题中的要求要求list
大小为 10 的整数以降序排列
命令。那么,让我们在 python 中生成一个列表。
# This meets the requirement.
# But it is a bit harder to wrap one's head around this. right?
>>> range(10-1, -1, -1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# let's find something that is a bit more self-explanatory. Sounds good?
# ----------------------------------------------------
# This returns a list in ascending order.
# Opposite of what the requirement called for.
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# This returns an iterator in descending order.
# Doesn't meet the requirement as it is not a list.
>>> reversed(range(10))
<listreverseiterator object at 0x10e14e090>
# This returns a list in descending order and meets the requirement
>>> list(reversed(range(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
【讨论】:
我真的很喜欢三元组-1
正是这种模式让wrap one's head around this
很容易保持-- 今天我了解到,如果它真的必须高效,在逆序遍历范围时使用range(n-1, -1, -1)
。【参考方案10】:
您可以使用 range() BIF Like 打印反向数字,
for number in range ( 10 , 0 , -1 ) :
print ( number )
输出将是 [10,9,8,7,6,5,4,3,2,1]
range() - 范围(开始、结束、递增/递减) 其中 start 是包容性的,end 是独占性的,并且 increment 可以是任何数字并且表现得像 step
【讨论】:
【参考方案11】:range(9,-1,-1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
【讨论】:
您的回答说明了为什么reversed(range(10))
不易出错。没有冒犯 Asinox。只是一个诚实的观察。
我不知道展示错误答案是否符合标准。我或其他人可以更正甚至删除它吗?
@sine,不,只是离开它,想知道它是如何累积 3 个赞成票的...我想您可以将其标记为版主注意(与 18 个月前的 answer 重复,但已损坏),不确定不管他们是否会删除它。
供所有将来参考:code only is not VLQ 和 wrong answers aren't supposed to be flagged either。投反对票并继续前进,但在这种情况下标记是错误的,无论是 NAA 还是 mod 标记。 - From review【参考方案12】:
使用不带 [::-1] 或反转 -
def reverse(text):
result = []
for index in range(len(text)-1,-1,-1):
c = text[index]
result.append(c)
return ''.join(result)
print reverse("python!")
【讨论】:
为什么要写这个而不是"python!"[::-1]
?【参考方案13】:
我相信这会有所帮助,
range(5)[::-1]
下面是用法:
for i in range(5)[::-1]:
print i
【讨论】:
【参考方案14】:我认为许多人(如我自己)可能对以相反的顺序遍历现有列表的常见情况更感兴趣,正如标题中所述,而不是仅仅为此类生成索引遍历。
尽管对于这种情况,所有正确的答案仍然非常好,但我想指出,在 Wolf's answer 中进行的性能比较仅用于生成索引。因此,我为以相反顺序遍历现有列表制定了类似的基准。
TL;DR a[::-1]
是最快的。
注意:如果您想更详细地分析不同的反转方案及其性能,请查看this great answer。
先决条件:
a = list(range(10))
Jason's answer:
%timeit [a[9-i] for i in range(10)]
1.27 µs ± 61.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
martineau's answer:
%timeit a[::-1]
135 ns ± 4.07 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Michał Šrajer's answer:
%timeit list(reversed(a))
374 ns ± 9.87 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
bene's answer:
%timeit [a[i] for i in range(9, -1, -1)]
1.09 µs ± 11.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
如您所见,在这种情况下,无需显式生成索引,因此最快的方法是减少额外操作的方法。
注意:我在 JupyterLab 中进行了测试,它有方便的“魔法命令”%timeit
。它在引擎盖下使用标准timeit.timeit
。已针对 Python 3.7.3 测试
【讨论】:
a[:: - 1]
的情况是最快的,因为你只计算了反转时间。如果你写得公平: * Janson 的回答:%timeit [9-i for i in range (10)]
* martineau 的回答:%timeit list(range(10)) [:: - 1]
* Michał Šrajer 的回答:%timeit list(reversed(range(10)))
* bene 的回答:%timeit list(range(9, -1, -1))
这些解决方案中的每一个都会给你一个列表。正如@Wolf 所示,最快的解决方案是bene's answer => range (9, -1, -1)
@Szczerski 现在,让我们假设 a = [3, 4, 100, 1, 20, -10, 0, 9, 5, 4]
在先决条件中。它会破坏您的代码,但不会破坏我的代码。我的答案是针对 arbitrary 列表已经给出的情况
如果您正在寻找“使用范围 () 以相反顺序打印列表?”问题的答案?你想知道哪种方式最快。这个解决方案是 bene 的答案。但是,如果您正在寻找最快的方式来反转您的列表a = [3, 4, 100, 1, 20, -10, 0, 9, 5, 4]
,那么请使用reverse()
而不是[:: - 1]
。 a.reverse ()
的速度是原来的两倍。
我不同意,或者我仍然错过了你的观点。同样,原始问题的答案大多与a = [0..9]
场景有关。对于更一般的情况,流行答案的时间安排可能会产生误导。我需要自己的时间,所以我做了并在这里分享了它们。我不想要就地反转——我只需要一个简单的列表,其中包含一个反向顺序的原始列表副本。当然,这个测试被大大简化了,结果可能/应该会因测试方案的不同而有所不同。【参考方案15】:
[9-i for i in range(10)]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
【讨论】:
【参考方案16】:您不一定需要使用 range 函数,您只需执行 list[::-1] 即可快速以相反的顺序返回列表,而无需使用任何添加。
【讨论】:
这似乎是previous answer 中建议的解决方案。看来您可能正在尝试对以前的不同答案发表评论 - 您需要获得更多声誉才能做到这一点。【参考方案17】:假设你有一个列表调用它 a=1,2,3,4,5 现在,如果您想反向打印列表,只需使用以下代码。
a.reverse
for i in a:
print(i)
我知道你问过使用范围,但它已经回答了。
【讨论】:
【参考方案18】:因为range(n)
产生了一个可迭代对象,所以你可以做各种各样的好事情来产生你想要的结果,例如:
range(n)[::-1]
如果循环没问题,我们可以做一个队列:
a = []
for i in range(n):
a.insert(0,a)
return a
或者可以使用 reverse() 方法:
reverse(range(n))
【讨论】:
reversed(range(n))
是否必须扩展内存中的整个范围?【参考方案19】:
range(9,-1,-1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
是正确的形式。如果你使用
reversed(range(10))
你不会得到一个 0 案例。例如,假设您的 10 不是一个幻数,并且您用于查找的变量是从反向开始的。如果您的 n 案例为 0,则不会执行 reversed(range(0)) 如果您碰巧在零索引中有一个对象,则这是错误的。
【讨论】:
以上是关于使用 range() 以相反的顺序打印列表?的主要内容,如果未能解决你的问题,请参考以下文章