2013-05-29 294 views
1

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

然而,这似乎并没有工作,我很茫然,为什么。任何帮助解决这个问题将不胜感激。

这是我此刻的代码:

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

+0

为什么你给你的变量,离奇和丑陋的名字呢? – abarnert

+0

目前它们只是占位符 – user2101517

+0

标准库包括[解析Python代码的模块](http://docs.python.org/3.3/library/ast.html)。 –

回答

6

这是一个令人难以置信的奇怪的设计。你打电话readlines得到的字符串列表,那么该列表,这将加入整个事情成一个大的字符串,每一行用逗号连接,并用方括号包围的报价repr上调用str,然后拆分结果在空间上。我不知道你为什么会这样做。

你离奇的变量名,像DICT_ = (dic)代码额外无用线等,只会进一步混淆的东西。

但我可以解释为什么它不起作用。试试你做的一切愚蠢后打印出DICT_,你会看到,包括while唯一键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。并将其扩展为处理iffor是微不足道的,也是显而易见的。


但是请注意,有一个在你的逻辑一个严重的问题:什么是像一个关键字,但在注释或字符串中间仍然会得到回升。如果没有写出某种代码去除评论和字符串,那么这是没有办法的。这意味着你会将iffor加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'])) 
+0

伟大的答案和使用'ast'模块的好例子。 –

+0

@JonClements:那么,我对AST的所有操作都是'walk'和'type(node)',所以它并没有真正展现你可以拥有的真正乐趣(例如,[MacroPy](https ://github.com/lihaoyi/macropy))。 – abarnert