Python中字符串中所有字符的ASCII值的总和

Mic*_*ael 11 python string ascii python-2.7

我正在寻找一种更有效的方法来总结给定字符串中所有字符的ASCII值,只使用标准的python(最好是2.7).

目前我有:

print sum(ord(ch) for ch in text)
Run Code Online (Sandbox Code Playgroud)

我想强调一下,这个问题的主要焦点和方面就是我上面写的内容.

以下是这个问题的一个不那么重要的方面,应该这样对待:

那我为什么要问呢?!我已经比较了这种方法与嵌入一个简单的C代码函数,它使用PyInline 在这里做同样的事情,而且看起来简单的C嵌入函数快17倍.

如果没有比我建议的更快的Python方法(仅使用标准的Python),那么Python开发人员没有在核心中添加这样的实现似乎很奇怪.

建议答案的当前结果.在我的Windows 7,i-7,Python 2.7上:

 text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
 sum(ord(ch) for ch in text)
 >> 0.00521324663262
 sum(array.array("B", text))
 >> 0.0010040770317
 sum(map(ord, text ))
 >> 0.00427160369234
 sum(bytearray(text))
 >> 0.000864669402933

 C-code embedded:
 >> 0.000272828426841
Run Code Online (Sandbox Code Playgroud)

use*_*342 20

您可以使用中间件bytearray加快速度:

>>> sum(bytearray("abcdefgh"))
804
Run Code Online (Sandbox Code Playgroud)

这不比生成器快17倍 - 它涉及创建一个中间体bytearray并且sum仍然需要迭代Python整数对象 - 但是在我的机器上它确实加速了从2μs到大约700ns的8个字符串的求和.如果这个球场的时间对于你的用例来说效率仍然太低,那么你应该用C编写应用程序的速度关键部分.

如果你的字符串足够大,并且你可以使用numpy,你可以通过直接引用字符串的缓冲区来避免创建临时副本numpy.frombuffer:

>>> import numpy as np
>>> np.frombuffer("abcdefgh", "uint8").sum()
804
Run Code Online (Sandbox Code Playgroud)

对于较小的字符串,由于numpy的视图创建机制的复杂性,这比临时数组慢.然而,对于足够大的弦,该frombuffer方法开始得到回报,并且它当然总是产生更少的垃圾.在我的机器上,截止点是大约200个字符的字符串大小.

另外,请参阅Guido的经典论文Python优化轶事.虽然它的一些特定技术现在可能已经过时,但如何考虑 Python优化的一般教训仍然非常重要.


您可以使用timeit模块计算不同的方法:

$ python -m timeit -s 's = "a" * 20' 'sum(ord(ch) for ch in s)' 
100000 loops, best of 3: 3.85 usec per loop
$ python -m timeit -s 's = "a" * 20' 'sum(bytearray(s))'
1000000 loops, best of 3: 1.05 usec per loop
$ python -m timeit -s 'from numpy import frombuffer; s = "a" * 20' \
                      'frombuffer(s, "uint8").sum()' 
100000 loops, best of 3: 4.8 usec per loop
Run Code Online (Sandbox Code Playgroud)

  • 你可以避免`import array`和`sum(array.array('B','abcdefgh'))`并且在使用2.7时只写`sum(bytearray('abcdefgh'))` (2认同)

Jon*_*nts 7

通过删除生成器的创建,你可以加速一点(~40%ish,但远不及本机C的速度快)...

代替:

sum(ord(c) for c in string)
Run Code Online (Sandbox Code Playgroud)

做:

sum(map(ord, string))
Run Code Online (Sandbox Code Playgroud)

时序:

>>> timeit.timeit(stmt="sum(map(ord, 'abcdefgh'))")
# TP: 1.5709713941578798
# JC: 1.425781011581421
>>> timeit.timeit(stmt="sum(ord(c) for c in 'abcdefgh')")
# TP: 1.7807035140629637
# JC: 1.9981679916381836
Run Code Online (Sandbox Code Playgroud)