在字典中计算单词(Python)

在字典中计算单词(Python),python,dictionary,counting,Python,Dictionary,Counting,我有一段代码,我想打开一个指定的文件,然后每次有一个while循环,它都会对它进行计数,最后输出一个特定文件中while循环的总数。我决定将输入文件转换为字典,然后创建一个for循环,每次看到单词while后跟空格时,它都会向while_u添加+1计数,最后在while_u末尾打印 然而,这似乎不起作用,我不知道为什么。如果您能帮助解决此问题,我们将不胜感激 这是我目前掌握的代码: WHILE_ = 0 INPUT_ = input("Enter file or directory: ")

我有一段代码,我想打开一个指定的文件,然后每次有一个while循环,它都会对它进行计数,最后输出一个特定文件中while循环的总数。我决定将输入文件转换为字典,然后创建一个for循环,每次看到单词while后跟空格时,它都会向while_u添加+1计数,最后在while_u末尾打印

然而,这似乎不起作用,我不知道为什么。如果您能帮助解决此问题,我们将不胜感激

这是我目前掌握的代码:

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_uuz=dic等等,只会让事情变得更加混乱

但我可以解释为什么它不起作用。在你做了所有这些愚蠢的事情之后,试着打印出DICT_uu,你会发现唯一包含while的键是while和'while。因为这两种模式都不匹配,所以您的计数最终为0

还值得注意的是,即使有多个模式实例,您也只能在WHILE_uu中添加1,因此您的整个计数记录是无用的

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

在这期间,我还将修复一些其他问题,以使代码可读、更简单,并且不会泄漏文件,等等。以下是您试图手工破解的逻辑的完整实现:

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代码,那么在标准库中进行解析显然是一种方法。如果您想为各种不同的语言编写快速而脏的解析器,请尝试,这非常好,并附带了一些很好的示例

下面是一个简单的例子:

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']))

这是一个不可思议的奇怪设计。您调用readlines来获取字符串列表,然后在该列表上调用str,这将把整个内容连接成一个大字符串,每行的repr用逗号连接,并用方括号括起来,然后在空格上拆分结果。我不知道你为什么会做这样的事

你奇怪的变量名,额外无用的代码行,比如DICT_uuz=dic等等,只会让事情变得更加混乱

但我可以解释为什么它不起作用。在你做了所有这些愚蠢的事情之后,试着打印出DICT_uu,你会发现唯一包含while的键是while和'while。因为这两种模式都不匹配,所以您的计数最终为0

还值得注意的是,即使有多个模式实例,您也只能在WHILE_uu中添加1,因此您的整个计数记录是无用的

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

在这期间,我还将修复一些其他问题,以使代码可读、更简单,并且不会泄漏文件,等等。以下是您试图手工破解的逻辑的完整实现:

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栏中。其次,不能用这种方式处理多行字符串

这些问题,以及其他类似的问题,是您几乎肯定需要真正的解析器的原因。如果您只是试图解析Python代码,那么在标准库中进行解析显然是一种方法。如果您想为各种不同的语言编写快速而脏的解析器,请尝试,这非常好,并附带了一些很好的示例

下面是一个简单的例子:

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']))

你为什么给你的变量起这么奇怪和难看的名字?它们现在只是标准库包含的占位符。这太令人费解了,甚至无法尝试和理解。可读性对你自己和他人都很重要——尤其是在你寻求帮助的时候。你为什么给你的变量起这么奇怪和难看的名字?它们现在只是标准库包含的占位符。这太令人费解了,甚至无法尝试和理解。可读性对你自己和他人都很重要,尤其是在你寻求帮助的时候。这是一个很好的答案,也是使用ast模块的一个很好的例子。@JonClements:好吧,我用ast所做的只是walk和typenode,所以它并没有真正展示你能从中获得的乐趣,例如。,。这是一个很好的答案,也是使用ast模块的一个很好的例子。@JonClements:嗯,我使用ast所做的只是walk和typenode,所以它并没有真正展示您使用它的乐趣,例如。