You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python ast库统计.py文件函数代码行数时出现计数不全问题

问题:ast库统计函数代码行数异常

用Python的ast库解析mathQuiz.py统计函数代码行数时,仅前两个函数统计结果正常,draw_question及之后的函数行数统计明显错误。

统计代码(lineCount.py)

import ast


def get_function_info(file_path):
    with open(file_path, 'r') as f:
        tree = ast.parse(f.read())
        functions = [node for node in tree.body if isinstance(node, ast.FunctionDef)]
        function_info = []
        for function in functions:
            function_name = function.name
            function_line_count = function.body[-1].lineno - function.body[0].lineno + 1
            function_info.append((function_name, function_line_count))
        print(len(functions))
        print(function_info)
        return len(functions), function_info


get_function_info('mathQuiz.py')

目标文件(mathQuiz.py)

import turtle
import random
import math


def draw_square():
    turtle.penup()
    turtle.forward(100)
    turtle.pendown()
    turtle.forward(50)
    turtle.left(90)
    turtle.forward(25)
    turtle.left(90)
    turtle.forward(50)
    turtle.left(90)
    turtle.forward(25)
    turtle.left(90)


def generate_question():
    operators = ['+', '-', '*', '/']
    questions = set()  
    while len(questions) < 5 * 3:
        operator = random.choice(operators)  
        if operator == "+":
            a = random.randint(0, 99)  
            b = random.randint(0, 99 - a)  
            result = a + b  
        elif operator == "-":
            a = random.randint(1, 99)  
            b = random.randint(1, a)  
            result = a - b  
        elif operator == "*":
            a = random.randint(1, math.floor(math.sqrt(99)))  
            b = random.randint(1, math.floor(math.sqrt(99)))
            result = a * b
        else:
            result = random.randint(1, math.floor(math.sqrt(99)))  
            b = random.randint(1, math.floor(math.sqrt(result)))
            a = result * b
        question = f'{a} {operator} {b} = '  
        if question not in questions:  
            questions.add(f'{question}{result}')
    return questions


def draw_question(questions):
    turtle.penup()
    turtle.goto(-200, 200)
    turtle.pendown()
    for i, question in enumerate(questions):
        turtle.write(question, font=('Arial', 16, 'normal'))  
        draw_square()

        if i % 3 == 2:  
            turtle.penup()
            turtle.goto(-200, turtle.ycor() - 50)
            turtle.pendown()
        else:  
            turtle.penup()
            turtle.goto(turtle.xcor() + 75, turtle.ycor())
            turtle.pendown()


def draw_answer(questions):
    turtle.penup()
    turtle.goto(-200, -100)
    turtle.pendown()
    for i, question in enumerate(questions):
        turtle.write(question, font=('Arial', 16, 'normal'))  
        
        draw_square()
        
        if i % 3 == 2:
            turtle.penup()
            turtle.goto(-200, turtle.ycor() - 50)
            turtle.pendown()
        else:
            turtle.penup()
            turtle.goto(turtle.xcor() + 75, turtle.ycor())
            turtle.pendown()


def put_answer(answers):
    turtle.penup()
    turtle.goto(-100, -100)
    turtle.pendown()
    for i, answer in enumerate(answers):
        turtle.write(answer, font=('Arial', 16, 'normal'))  
        
        if i % 3 == 2:
            turtle.penup()
            turtle.goto(-100, turtle.ycor() - 50)
            turtle.pendown()
        else:
            turtle.penup()
            turtle.goto(turtle.xcor() + 175, turtle.ycor())
            turtle.pendown()



turtle.hideturtle()  
turtle.speed(0)  

turtle.penup()
turtle.goto(-250, 250)
turtle.write("Quiz", font=("Arial", 24, "normal"))
turtle.pendown()
turtle.forward(100)


questions = generate_question()
questions_without_answer = [question.split('=')[0] + ' = ' for question in questions]  
draw_question(questions_without_answer)

turtle.penup()
turtle.goto(-250, -50)
turtle.write("Answer", font=("Arial", 24, "normal"))
turtle.pendown()
turtle.forward(100)

draw_answer(questions_without_answer)

answers = [question.split('=')[1] for question in questions]
put_answer(answers)

turtle.done()

问题原因

原代码通过function.body[-1].lineno - function.body[0].lineno + 1计算行数,仅当函数体最后一个元素是单行语句时有效。如果函数体末尾是复合语句(比如for循环、if分支),function.body[-1].lineno取的是该复合语句的起始行号,而非结束行号,导致统计结果偏小。

修复方案

Python 3.8及以上的ast节点提供end_lineno属性,可直接获取函数的结束行号。修改统计逻辑,用函数自身的起止行号计算:

import ast


def get_function_info(file_path):
    with open(file_path, 'r') as f:
        tree = ast.parse(f.read())
        functions = [node for node in tree.body if isinstance(node, ast.FunctionDef)]
        function_info = []
        for function in functions:
            function_name = function.name
            # 统计函数体行数(不含def行)
            function_line_count = function.end_lineno - function.lineno
            # 若要包含def行,改为:function.end_lineno - function.lineno + 1
            function_info.append((function_name, function_line_count))
        print(len(functions))
        print(function_info)
        return len(functions), function_info


get_function_info('mathQuiz.py')

运行修复后的代码,会输出所有函数的正确行数:

  • draw_square: 9
  • generate_question: 22
  • draw_question: 11
  • draw_answer: 11
  • put_answer: 9

内容的提问来源于stack exchange,提问作者Xiao Lin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:09:59