Python 是否需要范围(len(a))?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19184335/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a need for range(len(a))?
提问by Hyperboreus
One frequently finds expressions of this type in python questions on SO. Either for just accessing all items of the iterable
人们经常在关于 SO 的 python 问题中找到这种类型的表达式。要么只是访问可迭代的所有项目
for i in range(len(a)):
print(a[i])
Which is just a clumbersome way of writing:
这只是一种笨拙的写作方式:
for e in a:
print(e)
Or for assigning to elements of the iterable:
或者分配给可迭代的元素:
for i in range(len(a)):
a[i] = a[i] * 2
Which should be the same as:
这应该与以下内容相同:
for i, e in enumerate(a):
a[i] = e * 2
# Or if it isn't too expensive to create a new iterable
a = [e * 2 for e in a]
Or for filtering over the indices:
或者用于过滤索引:
for i in range(len(a)):
if i % 2 == 1: continue
print(a[i])
Which could be expressed like this:
可以这样表达:
for e in a [::2]:
print(e)
Or when you just need the length of the list, and not its content:
或者当您只需要列表的长度而不是其内容时:
for _ in range(len(a)):
doSomethingUnrelatedToA()
Which could be:
这可能是:
for _ in a:
doSomethingUnrelatedToA()
In python we have enumerate
, slicing, filter
, sorted
, etc... As python for
constructs are intended to iterate over iterables and not only ranges of integers, are there real-world use-cases where you need in range(len(a))
?
在 python 中,我们有enumerate
、切片、filter
、sorted
等......由于 pythonfor
构造旨在迭代可迭代对象而不仅仅是整数范围,是否有您需要的实际用例in range(len(a))
?
回答by Erik Kaplun
Short answer: mathematically speaking, no, in practical terms, yes, for example for Intentional Programming.
简短回答:从数学上讲,不,实际上,是的,例如意图编程。
Technically, the answer would be "no, it's not needed"because it's expressible using other constructs. But in practice, I use for i in range(len(a)
(or for _ in range(len(a))
if I don't need the index) to make it explicit that I want to iterate as many times as there are items in a sequence without needing to use the items in the sequence for anything.
从技术上讲,答案是“不,不需要”,因为它可以使用其他构造表达。但在实践中,我使用for i in range(len(a)
(或者for _ in range(len(a))
如果我不需要索引)明确表示我想迭代与序列中的项目一样多的次数,而无需将序列中的项目用于任何事情。
So: "Is there a need?"? — yes, I needit to express the meaning/intent of the code for readability purposes.
所以:“有必要吗?” ? — 是的,为了可读性,我需要它来表达代码的含义/意图。
See also: https://en.wikipedia.org/wiki/Intentional_programming
另见:https: //en.wikipedia.org/wiki/Intentional_programming
And obviously, if there is no collection that is associated with the iteration at all, for ... in range(len(N))
is the only option, so as to not resort to i = 0; while i < N; i += 1 ...
显然,如果根本没有与迭代相关联的集合,则for ... in range(len(N))
是唯一的选择,以免求助于i = 0; while i < N; i += 1 ...
回答by Jon Clements
If you need to work with indices of a sequence, then yes - you use it... eg for the equivalent of numpy.argsort...:
如果您需要使用序列的索引,那么是的 - 您可以使用它...例如相当于numpy.argsort...:
>>> a = [6, 3, 1, 2, 5, 4]
>>> sorted(range(len(a)), key=a.__getitem__)
[2, 3, 1, 5, 4, 0]
回答by Jon Clements
Going by the comments as well as personal experience, I say no, there is no needfor range(len(a))
. Everything you can do with range(len(a))
can be done in another (usually far more efficient) way.
被评论以及个人经验去,我说没有,就没有必要进行range(len(a))
。您可以用range(len(a))
另一种(通常更有效)的方式完成您可以使用的所有操作。
You gave many examples in your post, so I won't repeat them here. Instead, I will give an example for those who say "What if I want just the length of a
, not the items?". This is one of the only times you might consider using range(len(a))
. However, even this can be done like so:
你在帖子里举了很多例子,这里就不重复了。相反,我将为那些说“如果我只想要 的长度而a
不是项目?”的人举个例子。这是您可能会考虑使用range(len(a))
. 但是,即使这样也可以这样做:
>>> a = [1, 2, 3, 4]
>>> for _ in a:
... print True
...
True
True
True
True
>>>
Clements answer (as shown by Allik) can also be reworked to remove range(len(a))
:
Clements 的答案(如 Allik 所示)也可以重新修改以删除range(len(a))
:
>>> a = [6, 3, 1, 2, 5, 4]
>>> sorted(range(len(a)), key=a.__getitem__)
[2, 3, 1, 5, 4, 0]
>>> # Note however that, in this case, range(len(a)) is more efficient.
>>> [x for x, _ in sorted(enumerate(a), key=lambda i: i[1])]
[2, 3, 1, 5, 4, 0]
>>>
So, in conclusion, range(len(a))
is not needed. Its only upside is readability (its intention is clear). But that is just preference and code style.
所以,总而言之,range(len(a))
是不需要的。它唯一的好处是可读性(它的意图很明确)。但这只是偏好和代码风格。
回答by Charles Boncelet
Sometimes matplotlib requires range(len(y))
, e.g., while y=array([1,2,5,6])
, plot(y)
works fine, scatter(y)
does not. One has to write scatter(range(len(y)),y)
. (Personally, I think this is a bug in scatter
; plot
and its friends scatter
and stem
should use the same calling sequences as much as possible.)
有时 matplotlib 需要range(len(y))
,例如 while y=array([1,2,5,6])
,plot(y)
可以正常工作,scatter(y)
但不会。一要写scatter(range(len(y)),y)
。(就我个人而言,我认为这是scatter
;plot
及其朋友中的一个错误scatter
,stem
应该尽可能使用相同的调用序列。)
回答by Jim
I have an use case I don't believe any of your examples cover.
我有一个用例,我不相信您的任何示例都涵盖了。
boxes = [b1, b2, b3]
items = [i1, i2, i3, i4, i5]
for j in range(len(boxes)):
boxes[j].putitemin(items[j])
I'm relatively new to python though so happy to learn a more elegant approach.
我对 python 比较陌生,但很高兴学习一种更优雅的方法。
回答by IARI
Very simple example:
非常简单的例子:
def loadById(self, id):
if id in range(len(self.itemList)):
self.load(self.itemList[id])
I can't think of a solution that does not use the range-len composition quickly.
我想不出不快速使用 range-len 组合的解决方案。
But probably instead this should be done with try .. except
to stay pythonic i guess..
但可能相反,try .. except
我想应该这样做以保持 pythonic ..
回答by CleoR
It's nice to have when you need to use the index for some kind of manipulation and having the current element doesn't suffice. Take for instance a binary tree that's stored in an array. If you have a method that asks you to return a list of tuples that contains each nodes direct children then you need the index.
当您需要使用索引进行某种操作并且拥有当前元素还不够时,这是很好的。以存储在数组中的二叉树为例。如果你有一个方法要求你返回一个包含每个节点直接子节点的元组列表,那么你需要索引。
#0 -> 1,2 : 1 -> 3,4 : 2 -> 5,6 : 3 -> 7,8 ...
nodes = [0,1,2,3,4,5,6,7,8,9,10]
children = []
for i in range(len(nodes)):
leftNode = None
rightNode = None
if i*2 + 1 < len(nodes):
leftNode = nodes[i*2 + 1]
if i*2 + 2 < len(nodes):
rightNode = nodes[i*2 + 2]
children.append((leftNode,rightNode))
return children
Of course if the element you're working on is an object, you can just call a get children method. But yea, you only really need the index if you're doing some sort of manipulation.
当然,如果您正在处理的元素是一个对象,您可以只调用 get children 方法。但是,是的,只有在进行某种操作时才真正需要索引。
回答by Giswok
What if you need to access two elements of the list simultaneously?
如果您需要同时访问列表的两个元素怎么办?
for i in range(len(a[0:-1])):
something_new[i] = a[i] * a[i+1]
You can use this, but it's probably less clear:
您可以使用它,但可能不太清楚:
for i, _ in enumerate(a[0:-1]):
something_new[i] = a[i] * a[i+1]
Personally I'm not 100% happy with either!
就我个人而言,我对两者都不是 100% 满意!
回答by alexpirine
If you have to iterate over the first len(a)
items of an object b
(that is larger than a
), you should probably use range(len(a))
:
如果您必须迭代len(a)
对象的第一项b
(大于a
),您可能应该使用range(len(a))
:
for i in range(len(a)):
do_something_with(b[i])
回答by Mateen Ulhaq
Sometimes, you really don't care about the collection itself. For instance, creating a simple model fit line to compare an "approximation" with the raw data:
有时,您真的不关心集合本身。例如,创建一个简单的模型拟合线来比较“近似值”与原始数据:
fib_raw = [1, 1, 2, 3, 5, 8, 13, 21] # Fibonacci numbers
phi = (1 + sqrt(5)) / 2
phi2 = (1 - sqrt(5)) / 2
def fib_approx(n): return (phi**n - phi2**n) / sqrt(5)
x = range(len(data))
y = [fib_approx(n) for n in x]
# Now plot to compare fib_raw and y
# Compare error, etc
In this case, the values of the Fibonacci sequence itself were irrelevant. All we needed here was the size of the input sequence we were comparing with.
在这种情况下,斐波那契数列本身的值无关紧要。我们需要的只是我们要比较的输入序列的大小。