MST

星途 面试题库

面试题:Python自定义缩进错误自动化检查工具的设计与实现

假设现有一个项目,要求你设计并实现一个自定义的Python缩进错误自动化检查工具,以满足该项目特定的缩进规则需求。请详细描述你的设计思路,包括涉及的数据结构、算法,以及如何与Python代码解析相结合,同时给出关键代码示例。
35.3万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 数据结构
    • 使用列表来存储Python代码的每一行内容,方便按行处理。
    • 可以使用栈来跟踪缩进层次,在Python中,每遇到一个新的代码块(如函数定义、循环等),缩进层次增加;代码块结束,缩进层次减少。
  2. 算法
    • 逐行读取Python代码。
    • 计算每行代码的缩进量(通常以空格数或制表符数衡量)。
    • 利用栈来维护当前的缩进层次,遇到缩进增加的行,将新的缩进层次压入栈;遇到缩进减少的行,检查栈顶元素是否匹配当前缩进减少的量,如果不匹配则说明缩进错误。
    • 当遇到代码块开始的语句(如defiffor等),记录其缩进量;遇到代码块结束的标志(如elseeliffinally等),检查其缩进量是否与预期一致。
  3. 与Python代码解析相结合
    • 利用Python的内置模块tokenize来解析Python代码的词法单元。tokenize模块可以将Python代码分解为一个个的词法单元,包括关键字、标识符、操作符等,这样能更准确地判断代码块的开始和结束,而不仅仅依赖于缩进。
    • 通过分析词法单元序列,结合缩进量的计算,来全面检查缩进是否符合Python语法规则。

关键代码示例

import tokenize
from io import BytesIO


def check_indentation(code):
    stack = [0]  # 初始缩进层次为0
    last_token_type = None
    last_indent = 0
    for token_type, token, start, end, line in tokenize.tokenize(BytesIO(code.encode('utf-8')).readline):
        current_indent = len(line) - len(line.lstrip())
        if token_type == tokenize.INDENT:
            stack.append(current_indent)
        elif token_type == tokenize.DEDENT:
            if not stack or current_indent != stack.pop():
                raise IndentationError("Unexpected dedent")
        if token_type in (tokenize.NAME, tokenize.KEYWORD):
            if token in ('def', 'class', 'if', 'for', 'while', 'try'):
                last_token_type = token_type
                last_indent = current_indent
            elif token in ('else', 'elif', 'finally'):
                if last_token_type not in (tokenize.KEYWORD, tokenize.NAME) or current_indent != last_indent:
                    raise IndentationError(f"Invalid indentation for {token}")
    if stack:
        raise IndentationError("Unclosed block")
    return True


你可以使用以下方式调用这个函数:

code = """
def test():
    print('Hello')
"""
try:
    check_indentation(code)
    print("Indentation is correct")
except IndentationError as e:
    print(f"Indentation error: {e}")