只需要索引:枚举或(x)范围?

时间:2012-08-10 11:51:49

标签: python range enumerate

如果我只想在循环中使用索引,我应该更好地将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    

8 个答案:

答案 0 :(得分:17)

我会使用enumerate因为它更通用 - 例如它可以处理迭代和序列,而只返回对象的引用的开销并不是那么大 - 而xrange(len(something))虽然(对我来说)更容易理解你的意图 - 会破坏不支持len的对象......

答案 1 :(得分:15)

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

答案 2 :(得分:14)

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

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

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

使用下划线(_)也可能发生陷阱。在i18n库和系统中将'翻译'函数命名为_也很常见,所以要注意将它与gettext或其他类似的库一起使用(对@lazyr来说)。

答案 3 :(得分:4)

xrange应该快一点,但枚举意味着当你意识到你需要p afterall

时你不需要改变它

答案 4 :(得分: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]

答案 5 :(得分: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对来源发表评论时,您会看到范围(len())更快。

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

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

现在,如上所述评论我得到:

range(len()):
8.231641875551514
enum():
9.974262515773656

答案 6 :(得分:0)

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

最佳3,len(a)= 1M

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

希望它有所帮助。

仅供参考:我最初开始这个测试来比较python和vba的速度......并且发现vba实际上比范围方法快7倍......是因为我的蟒蛇技能差吗?

肯定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

答案 7 :(得分:-2)

只需使用range()即可。如果您要使用所有索引,xrange()没有任何实际好处(除非len(a)非常大)。 enumerate()创建了一个更丰富的数据结构,您将立即将其丢弃。