我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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(<type 'int'>, {'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之禅,“ 应该有一个&mdash;&mdash;宁肯只有一个明显的实现方法”。这句话所说的状态值得追求,但事实是,并不总是只有一种明显的方法。这个“明显”的方法会随着时间、需求和专业水平,不断地变化。

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

Python语言中计数方法的演变过程是怎么样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。有时候,利用Python语言简洁、优雅地解决问题的方法,会随着时间变化。随着Pyth
2023-06-17

Python 3.1核心语言的变化是怎么样的

Python 3.1核心语言的变化是怎么样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。这里我们将对Python 3.1核心语言的变化进行分析,包括字符串的格式化、说明符以及
2023-06-17

golang语言中wasm 环境搭建的过程是怎样的

本篇文章为大家展示了golang语言中wasm 环境搭建的过程是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。golang 安装通过官方地址 下载。MacOS 也可通过 brew 快速安装:$
2023-06-25

灵活性的Python编程语言是怎么样的

灵活性的Python编程语言是怎么样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。在了解Python编程语言之前,要理解下什么是Python编程语言?Cuido vanR
2023-06-17

Python编程语言的实现内幕是怎么样的

这篇文章将为大家详细讲解有关Python编程语言的实现内幕是怎么样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Python“ 时,他们可能想到的是有时称为 ”CPython“(因为它是以
2023-06-17

c语言变长数组定义的方法是什么

在C语言中,变长数组(Variable Length Arrays,VLA)可以通过指定数组大小为变量来定义。变长数组的大小在编译时确定,可以根据程序运行时的需要动态调整大小。变长数组的定义方法如下所示:int main() {int
c语言变长数组定义的方法是什么
2024-03-13

c语言变长数组初始化的方法是什么

在C语言中,变长数组是指数组的大小在编译时不确定,而是在运行时确定的数组。变长数组的初始化方法与普通数组相同,可以使用花括号{}来初始化数组的元素。例如:int size = 5;int arr[size] = {1, 2, 3, 4,
c语言变长数组初始化的方法是什么
2024-03-13

c语言中全局变量定义的方法是什么

在C语言中,全局变量可以在函数外部定义。以下是全局变量定义的方法:1. 在所有函数的外部定义变量,这样变量就可以在程序的任何地方访问。```cint globalVariable; // 全局变量定义```2. 在定义变量的同时进行初始化。
2023-09-29

C语言多线程局部变量共享的方法是什么

在C语言中,多线程之间共享局部变量是一种危险的行为,容易导致数据竞争和不确定的结果。因此,一般不推荐直接共享局部变量。然而,如果确实需要在多线程中共享局部变量,可以使用以下方法:将局部变量声明为静态变量:将局部变量声明为静态变量,使其在每
2023-10-27

c语言中函数的定义方法是什么

在C语言中,函数的定义通常包含以下几个部分:1. 返回类型:函数可以有不同的返回类型,如int、float、void等,用来表示函数返回的数据类型。2. 函数名:用来标识函数的名称,可以根据需要自定义。3. 参数列表:函数可以接受一定数量的
2023-09-29

go语言中方法和函数的区别是什么

区别:1、函数function是一段具有独立功能的代码,可以被反复多次调用,从而实现代码复用;而方法method是一个类的行为功能,只有该类的对象才能调用。2、方法有接受者,而函数无接受者。3、函数不可以重名,而方法可以重名。4、调用方式不一样。5、方法需要指定所属类型,可以是结构体也可以是自定义type,函数则通用。6、函数的形参与传参类型需要一致,方法可以改变。
2023-05-14

Go语言中的函数与方法怎么使用

这篇文章主要介绍了Go语言中的函数与方法怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Go语言中的函数与方法怎么使用文章都会有所收获,下面我们一起来看看吧。函数定义语法与大部分语言一致,Go语言中的函数
2023-07-02

windows电脑任务栏中没有语言栏的解决方法是怎样的

这期内容当中小编将会给大家带来有关windows电脑任务栏中没有语言栏的解决方法是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。问:我的电脑任务栏中没有语言栏,我在工具栏中的语言栏选项上已经选中显示
2023-06-14

python中文件操作的其他方法是怎么样的

今天就跟大家聊聊有关python中文件操作的其他方法是怎么样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。  Python中文件操作的一般方法,包括打开,写入,关闭。本文中介绍下
2023-06-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录