不止一次在微信、知乎有读者朋友跑过来问:看完了基础书,甚至看两遍了,但自己写的时候还是没思路,我该怎么办?
编程在我看来就是一门手艺活,绝不是简单通过看书就能学会的,跟学游泳、学车、学钢琴一个道理,没别的,掌握了最基本的理论之后就是干,只有通过大量的练习、实战才能掌握编程这门技能,之后再回过来头来继续深入理论
这个问题在知识星球也同样被问,于是在那里我们设了每日一题的专题,每周会出三道题给大家,做完之后要求提交到 GitHub,我会统一对代码进行 review。这些题一般都是出自于一些真实应用场景,通过这种方式来提高编程水平。
下面这道题我们在星球中的第三题,在你往下翻之前,不妨梳理下你的编程思路。
题目:
统计一个文件中每个单词出现的次数,列出出现频率最多的5个单词。
前言:
这道题在实际应用场景中使用比较广泛,记得哪里看到说李笑来就利用他的编程技能出版过一本背单词的畅销书,统计历年来四六级、托福考试中出现的高频词汇,学生根据词频来记单词,这种方式深受大家喜欢。这就是一个把编程技能用来解决实际问题的典型场景。
所以,哪怕你不是程序员,如果能掌握编程技能的话,也能给你的工作带来极大的便利。
另外,在做数据分析时,那些词云效果本质上都是基于词频统计来控制字体的大小,如果你能熟练运用Python中的知识来解决问题的话,那说明你真正入门Python了。
分析:
本题主要考察以下几个方面的知识点:
1、如何正确读写文件
在 Python 中读写文件可以使用内置函数open(),而 open 函数在python2 和 python3 中有一定的区别,比如 Python 中可以指定读写文件的编码格式,而 Python 则不可以,为了同时兼容2和3,我们通常会使用io模块下面的 open 函数,大家可以查文档搞清楚它们之间的区别,培养主动学习能力和查资料的习惯。
另外一点是读写文件完成之后是需要关闭文件描述符的,除了可以使用 try...except...finally的语法之后,我们还可以使用更优雅的 with … as 的语法来自动关闭文件。
2、如何对数据进行排序
sorted函数是一个使用频率很高的内置函数,它的用法也很强大,因为它可以通过指定参数 key 来进行自定义排序,也就意味着你不仅可以对数字排序、对字母排序、还可以对列表、字典、自定义的对象进行排序,你只需要要告诉 sorted 函数的排序规则是什么,比如一个people对象,我既可以根据年龄排序也可以根据身高体重来排序,所以这个函数时非常灵活的,另外,对于列表对象有自带的 sort 方法,如果能区分清楚 list.sort 与 sorted 之间区别那说明你已经能灵活运用了。
3、匿名函数的使用
刚说了sorted函数可以指定一个参数来控制排序的规则,这个参数可以是一个函数,这种场景往往匿名函数,就是我们常说的lambda函数显得很应景。
4、字典类型的运用
做词频统计,用字典无疑是最合适的数据类型,单词作为字典的key, 单词出现的次数作为字典的 value,很方便地就记录好了每个单词的频率,字典很像我们的电话本,每个名字关联一个电话号码。另外,字典最大的特点就是它的查询速度会非常快。理想情况下时间复杂度为O(1),我是说理想情况,如果你想深入了解字典的话,建议看看这篇文章。Python中提供了丰富的数据结构,要懂得根据应用场景正确选择合适的数据类型
5、正则表达式的运用
处理文本、字符串,正则表达式简直是神器,无论是做数据爬虫还是表单验证使用非常广泛,当然,正则表达式并不是 Python 特有的东西,所有编程语言都支持,我们除了学习正则表达式的基本规则之外就是Python中的re模块提供的各种函数了,只有熟悉了API 我们才能运用到实际场景中去。关于正则表达式推荐一篇文章:Python正则表达式操作指南
以上5点,每个点都可以整理出一篇文章出来
实现:
分析完之后,我们实现起来其实是非常快的。所以我们在拿到一个需求的时候,首先肯定是把需求弄清楚,想想大概可以用哪些技术来实现,随后才是动手写代码,其实我们在工作上,真正写代码的时间还不到一半。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# -*- coding:utf-8 -*- import io import re class Counter: def __init__( self , path): """ :param path: 文件路径 """ self .mapping = dict () with io. open (path, encoding = "utf-8" ) as f: data = f.read() words = [s.lower() for s in re.findall( "\w+" , data)] for word in words: self .mapping[word] = self .mapping.get(word, 0 ) + 1 def most_common( self , n): assert n > 0 , "n should be large than 0" return sorted ( self .mapping.items(), key = lambda item: item[ 1 ], reverse = True )[:n] if __name__ = = '__main__' : most_common_5 = Counter( "importthis.txt" ).most_common( 5 ) for item in most_common_5: print (item) #注:这里的文件是以Python之禅的19条格言保存到文本中进行统计的。 |
打印结果:
1
2
3
4
5
|
( 'is' , 10 ) ( 'better' , 8 ) ( 'than' , 8 ) ( 'the' , 6 ) ( 'to' , 5 ) |
总结
当然,实现方法不是唯一的。比如Python模块本身就提供了一个collections.Counter的类,它继承自dict类,就是用于做统计的,细心的你可能发现了,我实现的这个Counter和collections下面那个Counter很像,其实这就是造轮子,造轮子可以锻炼我们的编程思维,当然在工作上有现成的东西就没必要自己造轮子了,除非你有信心做得更好。你也可以思考假如Python没有提供Counter这个工具,你该怎么做。
另外,该模块还提供一个有序的字典对象 OrderedDict,使用它可以免去我们手动排序的操作。对于上面提及的知识点你是否都了然于心了,如果回答是的话,恭喜你,我想你应该掌握差不多了,进阶吧,如果你还有很多不清楚的地方,那么需要你更多的总结、练习。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。