千家信息网

Python语言中计数方法的演变过程是怎么样的

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,Python语言中计数方法的演变过程是怎么样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。有时候,利用Python语言简洁、优雅地解决
千家信息网最后更新 2026年11月01日Python语言中计数方法的演变过程是怎么样的

Python语言中计数方法的演变过程是怎么样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

有时候,利用Python语言简洁、优雅地解决问题的方法,会随着时间变化。随着Python不断进化,统计列表元素数量的方法也在改变。

以计算元素在列表中出现的次数为例,我们可以编写出许多不同的实现方法。在分析这些方法时,我们先不关注性能,只考虑代码风格。

要理解这些不同的实现方式,我们得先知道一些历史背景。幸运的是,我们生活在"future"世界,拥有一台时间机器。接下来,我们一起坐上时光机,回到1997年吧。

if 语句

1997年1月1日,我们使用的是Python 1.4。现在有一个不同颜色组成的列表,我们想知道列表里每种颜色出现的次数。我们用字典来计算吧!

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: if color_counts.has_key(c): color_counts[c] = color_counts[c] + 1 else: color_counts[c] = 1

注意:我们没有使用+=,因为增量赋值直到Python 2.0才出现;另外,我们也没有使用c in color_counts这个惯用法(idiom),因为这也是Python 2.2中才发明的,

运行上述代码之后,我们会发现color_counts字典里,现在包含了列表中每种颜色的出现次数。

>>> color_counts
{'brown': 3, 'yellow': 2, 'green': 1, 'black': 1, 'red': 1}

上面的实现很简单。我们遍历了每一种颜色,并判断该颜色是否在字典中。如果不在,就在字典加入该颜色;如果在,就增加这种颜色的计数。

我们还可以把上面的代码改写为:

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: if not color_counts.has_key(c): color_counts[c] = 0 color_counts[c] = color_counts[c] + 1

如果列表稀疏度高(即列表中不重复的颜色数量很多),这段代码可能运行的会有点慢。因为我们现在要执行两个语句,而不是一个。但是我们不关心性能问题,我们只关注编码风格。经过思考,我们决定采用新版的代码。

try代码块(Code Block)

1997年1月2日,我们使用的还是Python 1.4。今早醒来的时候,我们突然意识到:我们的代码遵循的是"三思而后行"(Look Before You Leap,即事先检查每一种可能出现的情况)原则,但实际上我们应该按照"获得谅解比获得许可容易"(Easier to Ask Forgiveness, Than Permission,即不检查,出了问题由异常处理来处理)的原则进行编程,因为后者更加简洁、优雅。我们用try-except代码块来重构下代码吧:

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: try: color_counts[c] = color_counts[c] + 1 except KeyError: color_counts[c] = 1

现在,我们的代码尝试增加每种颜色的计数。如果某颜色不在字典里,那么就会抛出KeyError,我们随之将该颜色的计数设置为1。

get方法

1998年1月1日,我们已经升级到了Python 1.5。我们决定重构之前的代码,使用字典中新增的get方法。

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: color_counts[c] = color_counts.get(c, 0) + 1

现在,我们的代码会遍历每种颜色,从字典中获取该颜色的当前计数值。如果没有这个计数值,则该颜色的计数值默认为0,然后在数值的基础上加1。***将字典中相应键的值设置为新的计数。

把主要代码都写在一行里,感觉很酷,但是我们不敢完全肯定这种做法更加简洁、优雅。我们觉得可能有点太聪敏了,所以还是撤销了这次的重构。

setdefault方法

2001年1月1日,我们现在使用的是Python 2.0。我们听说字典类型现在有一个setdefault方法,决定利用它重构我们的代码。我们还决定使用新增加的+=增量赋值运算符。

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = {} for c in colors: color_counts.setdefault(c, 0) color_counts[c] += 1

无论是否需要,我们在每一次循环时都会调用setdefault方法。但这样做,的确会让代码看上去可读性更高。我们发现这种方法比之前的代码更加简洁、优雅,所以提交了此次修改。

fromkeys方法

2004年1月1日,我们使用的是Python 2.3。我们听说字典新增了一个叫fromkeys的类方法(class method),可以利用列表中的元素作为键来构建字典。我们使用新方法重构了代码:

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = dict.fromkeys(colors, 0) for c in colors: color_counts[c] += 1

这段代码将不同的颜色作为键,创建了一个新的字典,每个键的值被默认设置为0。这样,我们增加每个键的值时,就不用担心是否已经进行了设置。我们也不需要在代码中进行检查或异常处理了,这看上去是个改进。我们决定就这样修改代码。

推导式(Comprehension)与集合

2005年1月1日,我们现在用的是Python 2.4。我们发现可以利用集合(Python 2.3中发布,2.4版成为内置类型)与列表推导式(Python 2.0中发布)来解决计数问题。进一步思考之后,我想起来Python 2.4中还发布了生成器表达式(generator expressions),我们***决定不用列表推导式,而是采用生成器表达式。

colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = dict((c, colors.count(c)) for c in set(colors))

注意:我们这里使用的不是字典推导式,因为字典推导式直到Python 2.7才被发明。

运行成功了,而且只有一行代码。但是这种代码够简洁、优雅吗 ?

我们想起了Python之禅(Zen of Python),这个Python编程指导原则起源于一个Python邮件列表,并悄悄地收进了Python 2.2.1版本中。我们在REPL(read-eval-print loop,交互式解释器)界面中输入import this:

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly. # 优美胜过丑陋
Explicit is better than implicit. # 明确胜过含蓄
Simple is better than complex. # 简单胜过复杂
Complex is better than complicated. # 复杂胜过难懂
Flat is better than nested. # 扁平胜过嵌套
Sparse is better than dense. # 稀疏胜过密集
Readability counts. # 易读亦有价
Special cases aren't special enough to break the rules. # 特例也不能特殊到打破规则
Although practicality beats purity. # 尽管实用会击败纯洁
Errors should never pass silently. # 错误永远不应默默地溜掉
Unless explicitly silenced. # 除非明确地使其沉默
In the face of ambiguity, refuse the temptation to guess. # 面对着不确定,要拒绝猜测的诱惑
There should be one-- and preferably only one --obvious way to do it. # 应该有一个–宁肯只有一个–明显的实现方法
Although that way may not be obvious at first unless you're Dutch. # 也许这个方法开始不是很明显,除非你是荷兰人
Now is better than never. #现在做也要胜过不去做
Although never is often better than right now. # 尽管不做通常好过立刻做
If the implementation is hard to explain, it's a bad idea. # 如果实现很难解释,那它就是一个坏想法
If the implementation is easy to explain, it may be a good idea. # 如果实现容易解释,那它可能就是一个好想法
Namespaces are one honking great idea -- let's do more of those! # 命名空间是一个响亮的出色想法就让我们多用用它们

我们的代码变得更复杂,时间复杂度从O(n)增加到了O(n2);还变的更丑,可读性更差了。我们那样改,是一次有趣的尝试,但是一行代码的实现形式,没有我们之前的方法简洁、优雅。我们***还是决定撤销修改。

defaultdict方法

2007年1月1日,我们使用的是Python 2.5。我们刚发现,defaultdict已经被加入标准库。这样,我们就可以把字典的默认键值设置为0了。让我们使用defaultdict重构代码:

from collections import defaultdict
colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = defaultdict(int) for c in colors: color_counts[c] += 1

那个for循环现在变得真简单!这样肯定是更加简洁、优雅了。

我们发现,color_counts这个变量的行为现在有点不同,但是它的确继承了字典的特性,支持所有相同的映射功能。

>>> color_counts
defaultdict(, {'brown': 3, 'yellow': 2, 'green': 1, 'black': 1, 'red': 1})

我们在这里没有把color_counts转换成字典,而是假设其他的代码也使用鸭子类型(duck typing, Python中动态类型的一种,这里的意思是:其他代码会将color_counts视作字典类型),不再改动这个类似字典的对象。

Counter类

2011年1月1日,我们使用的是Python 2.7。别人告诉我们,之前使用defaultdict编写的代码,不再是统计颜色出现次数最简洁、优雅的方法了。Python 2.7中新引入了一个Counter类,可以完全解决我们的问题。

from collections import Counter
colors = ["brown", "red", "green", "yellow", "yellow", "brown", "brown", "black"] color_counts = Counter(colors)

还有比这更简单的方法吗?这个一定是最简洁、优雅的实现了。

与defaultdict一样,Counter类返回的也是一个类似字典的对象(实际是字典的一个子类)。这对满足我们的需求来说足够了,所以我们就这么干了。

>>> color_counts
Counter({'brown': 3, 'yellow': 2, 'green': 1, 'black': 1, 'red': 1})

性能考虑

请注意,在编写这些实现方式时,我们都没有关注效率问题。大部分方法的时间复杂度相同(O(n)),但是不同的Python语言实现形式(如CPython, PyPy,或者Jython)下,运行时间会有差异。

尽管性能不是我们的主要关注点,我还是在CPython 3.5.0的实现下测试了运行时间。从中,你会发现一个有趣的现象:随着列表中颜色元素的密度(即相同元素的数量)变化,每一种实现方法的相对效率也会不同。

根据Python之禅," 应该有一个——宁肯只有一个明显的实现方法"。这句话所说的状态值得追求,但事实是,并不总是只有一种明显的方法。这个"明显"的方法会随着时间、需求和专业水平,不断地变化。

看完上述内容,你们掌握Python语言中计数方法的演变过程是怎么样的的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!

方法 代码 字典 颜色 简洁 优雅 问题 不同 时间 重构 复杂 明显 元素 类型 运行 语言 只有 性能 次数 还是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广州百单互联网科技有限公司 涨乐互联网科技 互联网科技未来 伴你行互联网科技有限公司 兼蜜互联网科技 国外互联网科技网站 互联网 科技服务平台 互联网科技公司招聘 科技赋能互联网健康 互联网科技博主是什么意思 互联网校园科技培训 中国航天科技大学国际工业互联网 互联网企业科技类企业如何做账 江苏互联网科技小贷 山东大美朱楼互联网科技有限公司 福建互联网展示科技馆设计 唯美互联网科技 悟空问答互联网科技 互联网科技创业有什么好项目 广州全民伙伴互联网科技有限公司 湖南永感互联网科技有限公司 美国互联网科技巨头监管 盛创互联网科技有限公司 青岛中康互联网医疗科技有限公司 科技类公司包括互联网吗 济南有互联网科技公司吗 上海钢联属于互联网科技股吗 互联网科技资金流入 半导体是互联网高科技吗 唯美互联网科技
0