1、题目背景
·深入理解列表使用方法,对瓦尔登湖的文本做一个词频统计,下载地址:Walden.txt_免费高速下载|百度网盘-分享无限制,下载后使用Pycharm打开文本重新保存一次,这是为了避免编码的问题。
2、代码调试和调整
·1、直接使用count()函数进行词频统计
path = 'D:/Walden.txt'
with open(path,'r') as text:
words = text.read().split()
print(words)
for word in words:
print('{}--{} times'.format(word,words.count(word)))
报错结果:
·说明以及调试:
path = 'D:/Walden.txt'
一、path路径
1、path的路径是你存放Walden的地址,注意文件路径不要有中文字符,我就是因为C盘有中文字符所以将文件放在D盘的,小白的话直接复制文件地址即可
2、关于路径里面‘\’和‘/’的说明
代码中处理文件路径时,使用斜杠(/
)或反斜杠(\
)作为目录分隔符的差异主要是由操作系统的不同导致的。不同的操作系统有不同的文件路径表示方式:
- Windows 系统通常使用反斜杠(
\
)作为文件路径的分隔符。例如,C:\Users\Example\file.txt
。 - Unix 基系统(包括Linux和macOS)使用斜杠(
/
)作为路径分隔符。例如,/Users/Example/file.txt
。
在Python和许多其他编程语言中,斜杠(/
)被视为跨平台的路径分隔符,可以在不同的操作系统中使用,而不需要修改代码。Python解释器会根据运行的操作系统自动处理这些路径,使其能够正确地访问文件系统。
另一方面,当在Windows系统上直接使用反斜杠(\
)时,需要注意转义字符的问题。在字符串中,\
被用作转义字符的引导,如\n
表示换行,\t
表示制表符。因此,如果你想在Windows系统的Python代码中使用反斜杠作为路径分隔符,你需要使用双反斜杠(\\
)来避免转义字符的意义,或者将字符串前加上r
,表示原始字符串,如r"C:\Users\Example\file.txt"
。
总之一句话,在(Windows中)路径里面你可以写‘\\’或者'/'都可以
即:
path = 'D:/Walden.txt'
path = 'D:\\Walden.txt'
二、文件打开
with open(path,'r') as text:
·如果直接运行上述代码,在Windows下会报错,报错命令如下:
'gbk' codec can't decode byte 0xbf in position 2: illegal multibyte sequence
遇到 'gbk' codec can't decode byte 0xbf in position 2: illegal multibyte sequence
这类错误时,通常意味着你尝试以默认编码(在Windows上通常是GBK)打开一个不是以该编码保存的文件。对于英文文本文件,它很可能是以UTF-8编码保存的,特别是如果它包含了任何非ASCII字符。
解决办法是:通过指定正确的编码格式来解决这个问题。如果你的文件是以UTF-8编码的,你可以在open
函数中指定encoding='utf-8'。即将第二行代码改为:
with open(path,'r',encodeing = 'utf-8') as text:
三、完整代码
path = 'D:\\Walden.txt'
with open(path,'r',encoding='utf-8') as text:
words = text.read().split()
print(words)
for word in words:
print('{}--{} times'.format(word,words.count(word)))
·运行结果部分截图:
仔细观察有以下问题:
1.有一些带标点符号的单词被单独统计了次数
2.有些单词不止一次地展示了出现的次数
3.由于python对大小写敏感,开头大写的单词被单独统计了
·2、调整统计方法,对单词做预处理
一、解决方案:
1.有一些带标点符号的单词被单独统计了次数——使用strip()函数去掉单词前后的标点符号,string.punctuation是一个字符串,包含了所有的标点符号,即strip(string.punctuation)去除一个单词里面出现的所有标点符号。
2.有些单词不止一次地展示了出现的次数——使用set()集合去掉重复出现的单词
3.由于python对大小写敏感,开头大写的单词被单独统计了——使用lower()函数将单词全部转化成小写,与第一个解决方法结合起来,可以写成:
word.strip(string.punctuation).lower() #word是你要进行处理的字符串
二、完整代码1.0版(适用于小型文本和日常文本)
import string
path = 'D:/Walden.txt'
with open(path,'r',encoding='utf-8') as text:
words = [raw_word.strip(string.punctuation).lower() for raw_word in text.read().split()]
words_index = set(words)
counts_dict = {index:words.count(index) for index in words_index}
for word in sorted(counts_dict,key=lambda x:counts_dict[x],reverse=True):
print('{}--{} times'.format(word,counts_dict[word]))
运行结果截图:
·说明:在运行这个代码过程中,你会发现他有很多for循环,所以运行之后需要一段时间才会给出运行结果,试想如果这个文本是超大文本,那运行的时间会呈指数式增长。(为2.0版本做铺垫)
代码解析:
-
导入
string
模块:这一步导入Python的string
模块,以便使用string.punctuation
获取所有的标点符号。 -
打开文件:使用
with open(path,'r',encoding='utf-8') as text
打开文件。这里指定了文件路径、读取模式('r'
表示读取)、和文件编码('utf-8'
)。with
语句确保文件在操作完成后会被正确关闭。 -
处理单词:通过列表推导式读取文件中的所有单词,去除每个单词前后的标点符号,然后转换为小写。这一步是为了统一单词的格式,便于后续的统计。
-
创建索引集合:
words_index = set(words)
创建了一个包含所有唯一单词的集合。使用集合是因为集合中的元素是唯一的,这样可以确保每个单词只被统计一次。 -
统计单词出现次数:
counts_dict = {index:words.count(index) for index in words_index}
通过字典推导式为每个唯一单词计算出现次数,并存储在counts_dict
中。这里words.count(index)
是一个相对低效的操作,因为它会对整个单词列表进行遍历来计算每个单词的出现次数。 -
打印结果:最后,通过一个
for
循环遍历counts_dict
,并使用sorted
函数按单词出现次数降序排序单词。lambda x: counts_dict[x]
是一个匿名函数,用于指定排序的依据(即单词出现的次数)。然后,使用print
语句打印每个单词及其出现次数。
·三、完整代码2.0版(适用于大型文本)
·3.1、问题重述:
完整代码1.0版有效地统计了文本文件中每个单词的出现次数,并按出现频率从高到低打印结果。不过,如之前所述,使用words.count(index)
进行计数是效率较低的,特别是对于较大的文本文件。一个更高效的方法是使用collections.Counter
对象,它可以直接从单词列表生成单词计数的字典,避免了多次遍历整个单词列表的需要。
·3.2、代码块:
import string
from collections import Counter
path = 'D:/Walden.txt'
with open(path, 'r', encoding='utf-8') as text:
# 使用列表推导式处理单词,去除标点符号并转换为小写
words = [raw_word.strip(string.punctuation).lower() for raw_word in text.read().split()]
# 使用Counter计算每个单词的出现次数
word_counts = Counter(words)
# 按照单词出现次数降序排序并打印
for word, count in word_counts.most_common():
print(f'{word}--{count} times') #f-strings(引入于Python 3.6),f在字符串开始前表示这是一
个格式化字符串。
·运行结果截图:
·解析说明:
·在这个修改后的版本中,我们使用Counter(words)
直接从处理后的单词列表words
中创建了一个Counter
对象word_counts
。Counter
对象是一个字典,其中的键是单词,值是对应的出现次数。
·Counter
类的most_common()
方法返回一个列表,其中包含了所有单词及其出现次数,按照次数降序排序。这样我们就可以直接遍历这个列表,并打印每个单词及其出现次数,而不需要手动排序。
·
`这种方法不仅代码更简洁,而且运行效率更高,特别是对于大型文本文件。
·也可以看出Python代码的优点在于丰富的库,可以极大简化运行时间和代码,提高运行速度。
3、总结
·编写代码的过程不是一蹴而就得,在之前的写代码过程中我总是想一遍就把代码的全部功能写出来,但是在看了很多入门书籍之后,我发现很多大型的编程文件都是先搭建一个框架,先实现基本功能,然后根据基本功能进行拓展和细化,以及根据代码出现的问题进行调试,然后逐步完善的,其实这个过程就是学习的过程,总有人想着一劳永逸,但是我相信一步步完善代码的过程才是编程的精髓吧。