Если вам нужен подход с чисто пирипарингом, это выглядит правильно:
from pyparsing import *
# lambda to define expressions
def makeExpr(ch):
expr = Literal(ch).setResultsName(ch, listAllMatches=True)
return expr
expr = OneOrMore(MatchFirst(makeExpr(c) for c in "abc"))
expr.setParseAction(lambda tokens: [[a,len(b)] for a,b in tokens.items()])
tests = """\
abc
bbbc
cccaa
""".splitlines()
for t in tests:
print t,expr.parseString(t).asList()
Печать:
abc [['a', 1], ['c', 1], ['b', 1]]
bbbc [['c', 1], ['b', 3]]
cccaa [['a', 2], ['c', 3]]
Но это начинает попадать в непонятную область кода, поскольку она опирается на некоторые из более загадочных функций pyparsing. В общем, мне нравятся частотомеры, которые используют defaultdict (еще не пробовал Counter), так как достаточно ясно, что вы делаете.