35

如果我只想在循环中使用索引,我是否应该更好地range/xrange结合使用该函数len()

a = [1,2,3]
for i in xrange(len(a)):
    print i 

还是enumerate?即使我根本不会使用p

for i,p in enumerate(a):
    print i    
4

8 回答 8

28

我会使用enumerate它,因为它更通用-例如,它将适用于可迭代对象和序列,并且仅返回对对象的引用的开销并不是什么大问题-xrange(len(something))尽管(对我而言)您的意图更容易阅读-将打破不支持len...的物体

于 2012-08-10T12:05:35.747 回答
19

将 xrange 与 len 一起使用是很常见的用例,所以是的,如果您只需要按索引访问值,则可以使用它。

但是,如果您出于某种原因更喜欢使用 enumerate,则可以使用下划线 (_),它只是一种常见的符号,表明您不会以某种有意义的方式使用该变量:

for i, _ in enumerate(a):
    print i

使用下划线 (_) 也可能会发生陷阱。在 i18n 库和系统中将“翻译”函数命名为 _ 也很常见,因此请注意将其与 gettext 或其他此类库一起使用(感谢@lazyr)。

于 2012-08-10T11:55:50.247 回答
16

这是一个罕见的要求——从容器中使用的唯一信息就是它的长度!在这种情况下,我确实会明确说明这一事实并使用第一个版本。

于 2012-08-10T11:53:14.397 回答
4

pxrange 应该快一点,但是 enumerate 将意味着当您意识到您毕竟需要时不需要更改它

于 2012-08-10T12:06:24.483 回答
3

我进行了时间测试,发现范围比枚举快约 2 倍。(在用于 Win32 的 python 3.6 上)

最好的 3,对于 len(a) = 1M

  • 枚举(a):0.125s
  • 范围(len(a)):0.058s

希望能帮助到你。

仅供参考:我最初开始这个测试是为了比较 python 和 vba 的速度……发现 vba 实际上比 range 方法快 7 倍……是因为我的 python 技能差吗?

当然python可以比vba做得更好

枚举脚本

import time
a = [0]
a = a * 1000000
time.perf_counter()

for i,j in enumerate(a):
    pass

print(time.perf_counter())

范围脚本

import time
a = [0]
a = a * 1000000
time.perf_counter()

for i in range(len(a)):
    pass

print(time.perf_counter())

vba 脚本 (0.008s)

Sub timetest_for()
Dim a(1000000) As Byte
Dim i As Long
tproc = Timer
For i = 1 To UBound(a)
Next i
Debug.Print Timer - tproc
End Sub
于 2018-01-27T16:37:46.733 回答
0

根据您的示例代码,

res = [[profiel.attr[i].x for i,p in enumerate(profiel.attr)] for profiel in prof_obj]

我会用

res = [[p.x for p in profiel.attr] for profiel in prof_obj]
于 2012-08-10T12:29:04.713 回答
0

我写这个是因为我想测试它。因此,这取决于您是否需要使用这些值。

代码:

testlist = []
for i in range(10000):
    testlist.append(i)

def rangelist():
    a = 0
    for i in range(len(testlist)):
        a += i
        a = testlist[i] + 1   # Comment this line for example for testing

def enumlist():
    b = 0
    for i, x in enumerate(testlist):
        b += i
        b = x + 1   # Comment this line for example for testing

import timeit
t = timeit.Timer(lambda: rangelist())
print("range(len()):")
print(t.timeit(number=10000))
t = timeit.Timer(lambda: enumlist())
print("enum():")
print(t.timeit(number=10000))

现在您可以运行它,并且很可能会得到结果,即 enum() 更快。当您评论源代码时a = testlist[i] + 1b = x + 1您会看到 range(len()) 更快。

对于上面的代码,我得到:

range(len()):
18.766527627612255
enum():
15.353173553868345

现在,当如上所述发表评论时,我得到:

range(len()):
8.231641875551514
enum():
9.974262515773656
于 2013-06-26T20:34:49.940 回答
-2

只需使用range(). 如果您无论如何都要使用所有索引,则xrange()不会提供任何真正的好处(除非len(a)真的很大)。并enumerate()创建一个更丰富的数据结构,您将立即丢弃。

于 2012-08-10T11:55:16.140 回答