Python 为什么是collections.Counter比'';。计数

Python 为什么是collections.Counter比'';。计数,python,performance,counter,Python,Performance,Counter,我有一个简单的任务:计算字符串中每个字母出现的次数。我使用了一个计数器(),但在一个论坛上,我看到了使用dict()/计数器()比对每个字母使用string.count()慢得多的信息。我认为它只会在字符串中交互一次,而string.count()解决方案必须在字符串中迭代四次(在本例中)。为什么Counter()这么慢 >>> timeit.timeit('x.count("A");x.count("G");x.count("C");x.count("T")', setup=

我有一个简单的任务:计算字符串中每个字母出现的次数。我使用了一个
计数器()
,但在一个论坛上,我看到了使用
dict()
/
计数器()
比对每个字母使用
string.count()
慢得多的信息。我认为它只会在字符串中交互一次,而
string.count()
解决方案必须在字符串中迭代四次(在本例中)。为什么
Counter()
这么慢

>>> timeit.timeit('x.count("A");x.count("G");x.count("C");x.count("T")', setup="x='GAAAAAGTCGTAGGGTTCCTTCACTCGAGGAATGCTGCGACAGTAAAGGAGGCCACGTGGTTGAGAGTTCCTAAGCATTCGTATGTACACCCGGACTCGATGCACTCAAACGTGCTTAAGGGTAAAGAAGGTCGAGAGGTATACTGGGGCACTCCCCTTAGAATTATATCTTGGTCAACTACAATATGGATGGAAATTCTAAGCCGAAAACGACCCGCTAGCGGATTGTGTATGTATCACAACGGTTTCGGTTCATACGCAAAATCATCCCATTTCAAGGCCACTCAAGGACATGACGCCGTGCAACTCCGAGGACATCCCTCAGCGATTGATGCAACCTGGTCATCTAATAATCCTTAGAACGGATGTGCCCTCTACTGGGAGAGCCGGCTAGACTGGCATCTCGCGTTGTTCGTACGAGCTCCGGGCGCCCGGGCGGTGTACGTTGATGTACAGCCTAAGAGCTTTCCACCTATGCTACGAACTAATTTCCCGTCCATCGTTCCTCGGACTGAGGTCAAAGTAACCCGGAAGTACATGGATCAGATACACTCACAGTCCCCTTTAATGACTGAGCTGGACGCTATTGATTGCTTTATAAGTGTTATGGTGAACTCGAAGACTTAGCTAGGAATTTCGCTATACCCGGGTAATGAGCTTAATACCTCACAGCATGTACGCTCTGAATATATGTAGCGATGCTAGCGGAACGTAAGCGTGAGCGTTATGCAGGGCTCCGCACCTCGTGGCCACTCGCCCAATGCCCGAGTTTTTGAGCAATGCCATGCCCTCCAGGTGAAGCGTGCTGAATATGTTCCGCCTCCGCACACCTACCCTACGGGCCTTACGCCATAGCTGAGGATACGCGAGTTGGTTAGCGATTACGTCATTCCAGGTGGTCGTTC'", number=10000)
0.07911698750407936
>>> timeit.timeit('Counter(x)', setup="from collections import Counter;x='GAAAAAGTCGTAGGGTTCCTTCACTCGAGGAATGCTGCGACAGTAAAGGAGGCCACGTGGTTGAGAGTTCCTAAGCATTCGTATGTACACCCGGACTCGATGCACTCAAACGTGCTTAAGGGTAAAGAAGGTCGAGAGGTATACTGGGGCACTCCCCTTAGAATTATATCTTGGTCAACTACAATATGGATGGAAATTCTAAGCCGAAAACGACCCGCTAGCGGATTGTGTATGTATCACAACGGTTTCGGTTCATACGCAAAATCATCCCATTTCAAGGCCACTCAAGGACATGACGCCGTGCAACTCCGAGGACATCCCTCAGCGATTGATGCAACCTGGTCATCTAATAATCCTTAGAACGGATGTGCCCTCTACTGGGAGAGCCGGCTAGACTGGCATCTCGCGTTGTTCGTACGAGCTCCGGGCGCCCGGGCGGTGTACGTTGATGTACAGCCTAAGAGCTTTCCACCTATGCTACGAACTAATTTCCCGTCCATCGTTCCTCGGACTGAGGTCAAAGTAACCCGGAAGTACATGGATCAGATACACTCACAGTCCCCTTTAATGACTGAGCTGGACGCTATTGATTGCTTTATAAGTGTTATGGTGAACTCGAAGACTTAGCTAGGAATTTCGCTATACCCGGGTAATGAGCTTAATACCTCACAGCATGTACGCTCTGAATATATGTAGCGATGCTAGCGGAACGTAAGCGTGAGCGTTATGCAGGGCTCCGCACCTCGTGGCCACTCGCCCAATGCCCGAGTTTTTGAGCAATGCCATGCCCTCCAGGTGAAGCGTGCTGAATATGTTCCGCCTCCGCACACCTACCCTACGGGCCTTACGCCATAGCTGAGGATACGCGAGTTGGTTAGCGATTACGTCATTCCAGGTGGTCGTTC'", number=10000)
2.1727447831030844
>>> 2.1727447831030844 / 0.07911698750407936
27.462430656767047
>>> 

计数器
类继承自
dict
,而
string.count
是以下C实现(CPython 3.3):

/*stringlib:count实现*/
#ifndef STRINGLIB\u FASTSEARCH\u
#在包含此模块之前,错误必须包含“stringlib/fastsearch.h”
#恩迪夫
Py_LOCAL_INLINE(Py_ssize_t)
STRINGLIB(计数)(常量STRINGLIB_CHAR*str,Py_ssize_t str_len,
常量STRINGLIB_CHAR*sub,Py_ssize_t sub_len,
Py_ssize_t最大计数)
{
Py_-ssize_-t计数;
如果(str_len<0)
返回0;/*start>len(str)*/
if(sub_len==0)
返回(str_len
猜猜看,哪一个更快?:)

Counter()
允许您计算任何可散列对象,而不仅仅是子字符串。两种解决方案都是
O(n)
-时间。您的测量结果表明,通过
Counter()
对单个字符进行迭代和散列的开销大于运行
s.count()
4次

Counter()
可以使用C helper来计算元素,但它似乎没有特殊情况的字符串,并且使用了适用于任何其他iterable的通用算法,即:

while(1){
key=PyIter_Next(it);
if(key==NULL)
打破
oldval=PyObject_GetItem(映射,键);
如果(oldval==NULL){
如果(!PyErr_发生()| |!PyErr_异常匹配(PyExc_KeyError))
打破
PyErr_Clear();
Py_增量(一个);
newval=1;
}否则{
newval=PyNumber\u Add(oldval,一);
Py_DECREF(oldval);
if(newval==NULL)
打破
}
if(PyObject_SetItem(映射、键、newval)=-1)
打破
Py_CLEAR(newval);
Py_DECREF(键);
}
将其与ByTestRing的开销进行比较:

(i=0;i 如果(s[i]==p[0]){ 计数++; if(count==maxcount) 返回最大计数; } 返回计数;
它不是算法-
x.count()
意味着你每检查一项循环一次,
计数器()只循环一次。可能这种情况下的管理费用高于储蓄。相关:
/* stringlib: count implementation */

#ifndef STRINGLIB_FASTSEARCH_H
#error must include "stringlib/fastsearch.h" before including this module
#endif


Py_LOCAL_INLINE(Py_ssize_t)
STRINGLIB(count)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
                Py_ssize_t maxcount)
{
    Py_ssize_t count;

    if (str_len < 0)
        return 0; /* start > len(str) */
    if (sub_len == 0)
        return (str_len < maxcount) ? str_len + 1 : maxcount;

    count = FASTSEARCH(str, str_len, sub, sub_len, maxcount, FAST_COUNT);

    if (count < 0)
        return 0; /* no match */

    return count;
}