【问题标题】:How to count the occurrences of keywords in code but ignore the ones in comment / docstring?如何计算代码中关键字的出现次数,但忽略注释/文档字符串中的关键字?
【发布时间】:2015-05-14 08:14:16
【问题描述】:

我是 Python 的新手。我想在下面的代码中找到 Python 关键字 ['def','in', 'if'...] 的出现。但是,需要忽略代码中任何字符串常量中的关键字。 如何在不计算字符串中的关键字的情况下计算关键字的出现次数?

def grade(result):
    '''
    if if (<--- example to test if the word "if" will be ignored in the counts)
    :param result: none
    :return:none
    '''

    if result >= 80:
        grade = "HD"
    elif 70 <= result:
        grade = "DI"
    elif 60 <= result:
        grade = "CR"
    elif 50 <= result:
        grade = "PA"
    else:
    #else (ignore this word)
        grade = "NN"
    return grade

result = float(raw_input("Enter a final result: "))

while result < 0 or result > 100:
    print "Invalid result. Result must be between 0 and 100."
    result = float(raw_input("Re-enter final result: "))

print "The corresponding grade is", grade(result)

【问题讨论】:

    标签: python file python-2.7 count keyword


    【解决方案1】:

    使用tokenizekeywordcollections 模块。

    tokenize.generate_tokens(readline)

    generate_tokens() 生成器 需要一个参数 readline,它必须是一个可调用对象 提供与内置文件的 readline() 方法相同的接口 对象(请参阅文件对象部分)。对函数的每次调用都应该 将一行输入作为字符串返回。或者, readline 可能是 通过引发 StopIteration 发出完成信号的可调用对象。

    生成器生成具有以下成员的 5 元组:令牌类型令牌字符串;指定行的整数的 2 元组 (srow, scol) 以及令牌在源中开始的列;一个 2 元组 (erow, ecol) 的整数,指定标记结束的行和列 来源;以及找到令牌的行。线路通过 (最后一个元组项)是逻辑行;续行是 包括在内。

    2.2 版中的新功能。

    import tokenize
    with open('source.py') as f:
        print list(tokenize.generate_tokens(f.readline))
    

    部分输出:

    [(1, 'def', (1, 0), (1, 3), 'def grade(result):\n'),
     (1, 'grade', (1, 4), (1, 9), 'def grade(result):\n'),
     (51, '(', (1, 9), (1, 10), 'def grade(result):\n'),
     (1, 'result', (1, 10), (1, 16), 'def grade(result):\n'),
     (51, ')', (1, 16), (1, 17), 'def grade(result):\n'),
     (51, ':', (1, 17), (1, 18), 'def grade(result):\n'),
     (4, '\n', (1, 18), (1, 19), 'def grade(result):\n'),
     (5, '    ', (2, 0), (2, 4), "    '''\n"),
     (3,
      '\'\'\'\n    if if (<--- example to test if the word "if" will be ignored in the counts)\n    :param result: none\n    :return:none\n    \'\'\'',
      (2, 4),
      (6, 7),
      '    \'\'\'\n    if if (<--- example to test if the word "if" will be ignored in the counts)\n    :param result: none\n    :return:none\n    \'\'\'\n'),
     (4, '\n', (6, 7), (6, 8), "    '''\n"),
     (54, '\n', (7, 0), (7, 1), '\n'),
     (1, 'if', (8, 4), (8, 6), '    if result >= 80:\n'),
    

    您可以从keyword 模块中检索关键字列表:

    import keyword
    print keyword.kwlist
    print keyword.iskeyword('def')
    

    与 collections.Counter 的集成解决方案:

    import tokenize
    import keyword
    import collections 
    with open('source.py') as f:
        # tokens is lazy generator
        tokens = (token for _, token, _, _, _ in tokenize.generate_tokens(f.readline))
        c = collections.Counter(token for token in tokens if keyword.iskeyword(token))
    
    print c  # Counter({'elif': 3, 'print': 2, 'return': 1, 'else': 1, 'while': 1, 'or': 1, 'def': 1, 'if': 1})
    

    【讨论】:

    • 哇,我很抱歉两年前没有接受你的回答。当我第一次参加编程入门课程时,我问了这个问题,当时我无法理解和实现你的代码。非常感谢您的回答!
    猜你喜欢
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    相关资源
    最近更新 更多