Skip to main content
 首页 » 编程设计

python之计算字典中的单词数(Python)

2025年05月04日18oomusou

我有这样一段代码,我想打开一个指定的文件,然后每次有while循环就会统计,最后输出一个特定文件的while循环总数。我决定将输入文件转换为字典,然后创建一个 for 循环,每次看到 while 后跟一个空格的单词时,它都会在最后打印 WHILE_ 之前为 WHILE_ 添加 +1 计数。

然而这似乎并没有奏效,我不知道为什么。任何解决此问题的帮助将不胜感激。

这是我目前的代码:

WHILE_ = 0 
INPUT_ = input("Enter file or directory: ") 
 
 
OPEN_ = open(INPUT_) 
READLINES_ = OPEN_.readlines() 
STRING_ = (str(READLINES_)) 
STRIP_ = STRING_.strip() 
input_str1 = STRIP_.lower() 
 
 
dic = dict() 
for w in input_str1.split(): 
    if w in dic.keys(): 
        dic[w] = dic[w]+1 
    else: 
        dic[w] = 1 
DICT_ = (dic) 
 
 
for LINE_ in DICT_: 
    if  ("while\\n',") in LINE_: 
        WHILE_ += 1 
    elif ('while\\n",') in LINE_: 
        WHILE_ += 1 
    elif ('while ') in LINE_: 
        WHILE_ += 1 
 
print ("while_loops {0:>12}".format((WHILE_))) 

这是我使用的输入文件:

'''A trivial test of metrics 
Author: Angus McGurkinshaw 
Date: May 7 2013 
''' 
 
def silly_function(blah): 
    '''A silly docstring for a silly function''' 
    def nested(): 
        pass 
    print('Hello world', blah + 36 * 14) 
    tot = 0  # This isn't a for statement 
    for i in range(10): 
        tot = tot + i 
        if_im_done = false  # Nor is this an if 
    print(tot) 
 
blah = 3 
while blah > 0: 
    silly_function(blah) 
    blah -= 1 
    while True: 
        if blah < 1000: 
            break 

输出应该是 2,但我的代码现在打印 0

请您参考如下方法:

这是一个非常奇怪的设计。您正在调用 readlines 来获取字符串列表,然后在该列表上调用 str,这会将整个字符串连接成一个带有引号 的大字符串repr 每行用逗号连接并用方括号括起来,然后用空格分割结果。我不知道你为什么要这样做。

你奇怪的变量名,额外的无用代码行,如 DICT_ = (dic) 等只会进一步混淆事物。

但我可以解释为什么它不起作用。在你做了所有这些愚蠢的事情之后尝试打印出 DICT_,你会看到唯一包含 while 的键是 while 和 '同时。由于这些都不匹配您要查找的任何模式,因此您的计数最终为 0。

同样值得注意的是,即使模式有多个实例,您也只将 1 添加到 WHILE_,因此您的整个计数字典是无用的。


如果您不混淆您的字符串,尝试恢复它们,然后尝试匹配错误恢复的版本,这将容易得多。直接做就行了。

同时,我还将解决一些其他问题,以便您的代码可读、更简单、不会泄漏文件等。这是您尝试手动破解的逻辑的完整实现:​​

import collections 
 
filename = input("Enter file: ") 
counts = collections.Counter() 
with open(filename) as f: 
    for line in f: 
        counts.update(line.strip().lower().split()) 
print('while_loops {0:>12}'.format(counts['while'])) 

当您在样本输入上运行它时,您会正确地得到 2。并将其扩展为处理 if 和 for 是微不足道且显而易见的。


但是,请注意您的逻辑中存在一个严重的问题:任何看起来像关键字但位于评论或字符串中间的内容仍会被选取。如果不编写某种代码来删除注释和字符串,就没有办法解决这个问题。这意味着您要将 if 和 for 多算 1。显而易见的剥离方式—line.partition('#')[0] 和类似的引号——将不起作用。首先,在 if 关键字之前有一个字符串是完全有效的,例如 "foo"if x else "bar"。其次,您不能以这种方式处理多行字符串。

这些问题,以及其他类似的问题,就是您几乎肯定需要一个真正的解析器的原因。如果您只是想解析 Python 代码,the ast module在标准库中是执行此操作的明显方法。如果你想为各种不同的语言编写快速和脏的解析器,试试 pyparsing ,这非常好,并附带了一些很好的例子。

这是一个简单的例子:

import ast 
 
filename = input("Enter file: ") 
with open(filename) as f: 
    tree = ast.parse(f.read()) 
while_loops = sum(1 for node in ast.walk(tree) if isinstance(node, ast.While)) 
print('while_loops {0:>12}'.format(while_loops)) 

或者,更灵活地:

import ast 
import collections 
 
filename = input("Enter file: ") 
with open(filename) as f: 
    tree = ast.parse(f.read()) 
counts = collections.Counter(type(node).__name__ for node in ast.walk(tree))     
print('while_loops {0:>12}'.format(counts['While'])) 
print('for_loops {0:>14}'.format(counts['For'])) 
print('if_statements {0:>10}'.format(counts['If']))