在python中,什么更有效?修改列表或字符串?

时间:2010-02-12 16:18:32

标签: python list string

无论易用性如何,计算效率更高?不断切片列表并附加到它们?或者采取子串并做同样的事情?

举个例子,假设我有两个二进制字符串“11011”和“01001”。如果我将这些表示为列表,我将选择一个随机的“切片”点。让我说我得到3.我将获取第一个字符串的前3个字符和第二个字符串的剩余字符(所以我必须将它们切片)并从中创建一个新字符串。

通过切割子串或将其表示为列表([1,1,0,1,1])而不是字符串,可以更有效地完成这项工作吗?

4 个答案:

答案 0 :(得分:7)

>>> a = "11011"
>>> b = "01001"
>>> import timeit
>>> def strslice():
    return a[:3] + b[3:]

>>> def lstslice():
    return list(a)[:3] + list(b)[3:]
>>> c = list(a)
>>> d = list(b)
>>> def lsts():
    return c[:3] + d[3:]

>>> timeit.timeit(strslice)
0.5103488475836432
>>> timeit.timeit(lstslice)
2.4350100538824613
>>> timeit.timeit(lsts)
1.0648406858527295

答案 1 :(得分:5)

timeit是微型基准测试的一个很好的工具,但是当您想要比较的操作可能涉及就地更改时,需要非常小心地使用它 - 在这种情况下,您需要包括旨在制作所需副本的额外操作。然后,第一次只是“额外”开销:

$ python -mtimeit -s'a="11011";b="01001"' 'la=list(a);lb=list(b)'
100000 loops, best of 3: 5.01 usec per loop
$ python -mtimeit -s'a="11011";b="01001"' 'la=list(a);lb=list(b)'
100000 loops, best of 3: 5.06 usec per loop

因此,制作我们需要的两个全新列表(避免更改)需要花费超过5微秒(当关注小差异时,至少运行2-3次以观察不确定性范围)。之后:

$ python -mtimeit -s'a="11011";b="01001"' 'la=list(a);lb=list(b);x=a[:3]+b[3:]'
100000 loops, best of 3: 5.5 usec per loop
$ python -mtimeit -s'a="11011";b="01001"' 'la=list(a);lb=list(b);x=a[:3]+b[3:]'
100000 loops, best of 3: 5.47 usec per loop
在这种情况下,字符串切片和连接可以看作另外花费410-490纳秒。和

$ python -mtimeit -s'a="11011";b="01001"' 'la=list(a);lb=list(b);la[3:]=lb[3:]'
100000 loops, best of 3: 5.99 usec per loop
$ python -mtimeit -s'a="11011";b="01001"' 'la=list(a);lb=list(b);la[3:]=lb[3:]'
100000 loops, best of 3: 5.99 usec per loop

就地列表拼接可以看作花费930-980纳秒。差异安全地高于噪声/不确定性水平,因此您可以可靠地声明,对于此用例,使用字符串将花费大约一半的时间与使用列表就地工作。当然,衡量一系列与您典型的瓶颈任务相关的用例也很重要!

答案 2 :(得分:4)

通常,修改列表比修改字符串更有效,因为字符串是不可变的。

答案 3 :(得分:0)

这实际上取决于实际用例,正如其他人所说,对其进行概要分析,但一般来说,附加到列表会更好,因为它可以在适当的位置完成,而“追加到字符串”实际上会创建一个新的字符串连接旧字符串。这可以迅速消耗记忆力。 (实际上,这与计算效率不同)。

编辑:如果您希望使用二进制值计算效率,请不要使用字符串或列表。使用整数和按位运算。使用最新版本的python,您可以在需要时使用二进制表示:

>>> bin(42)
'0b101010'
>>> 0b101010
42
>>> int('101010')
101010
>>> int('101010', 2)
42
>>> int('0b101010')
...
ValueError: invalid literal for int() with base 10: '0b101010'
>>> int('0b101010', 2)
42

编辑2:

def strslice(a, b):
    return a[:3] + b[3:]

可能更好地写成:

def binspice(a, b):
    mask = 0b11100
    return (a & mask) + (b & ~mask)

>>> a = 0b11011
>>> b = 0b1001
>>> bin(binsplice(a, b))
'0b11001
>>> 

如果二进制数不同,可能需要修改。