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

使用global声明后变量仍未定义?Python实现COOL编译器遇NameError

解决COOL编译器Lexer中NameError: name 'comm_reg' is not defined的问题

你遇到的问题核心是混淆了类属性和全局变量的作用域,这里给你拆解原因和解决办法:

错误根源

你在CoolLexer类里定义了comm_reg作为类属性,但在方法中使用global comm_reg声明——global关键字的作用是告诉Python去模块级别的全局命名空间找这个变量,而不是类内部的命名空间。所以Python找不到comm_reg,就抛出了NameError。

解决方案

根据你的需求(维护Lexer的注释状态),有两种更合理的实现方式:

方式1:使用类属性(共享状态)

如果所有CoolLexer实例需要共享同一个注释状态,直接通过类名访问类属性即可,不需要global声明:

class CoolLexer(Lexer):
    comm_reg = False
    comm_line = False

    @_(r'[(][\*]')
    def COMMENT(self, t):
        # 直接通过类名修改类属性
        CoolLexer.comm_reg = True

    @_(r'[*][)]')
    def CLOSE_COMMENT(self, t):
        if CoolLexer.comm_reg:
            CoolLexer.comm_reg = False
        else:
            return t

    @_(r'[-][-].*')
    def ONE_LINE_COMMENT(self, t):
        CoolLexer.comm_line = True

    def salida(self, texto):
        list_strings = []
        for token in lexer.tokenize(texto):
            if CoolLexer.comm_reg:
                continue
            elif CoolLexer.comm_line:
                CoolLexer.comm_line = False
                continue
            result = f'#{token.lineno} {token.type} '
            # 记得把result添加到list_strings中,比如:
            list_strings.append(result)
        return list_strings

方式2:使用实例属性(独立状态)

如果每个CoolLexer实例需要独立维护自己的注释状态(更符合面向对象设计的常规做法),把属性移到__init__方法中,用self访问:

class CoolLexer(Lexer):
    def __init__(self):
        # 初始化实例属性
        self.comm_reg = False
        self.comm_line = False

    @_(r'[(][\*]')
    def COMMENT(self, t):
        self.comm_reg = True

    @_(r'[*][)]')
    def CLOSE_COMMENT(self, t):
        if self.comm_reg:
            self.comm_reg = False
        else:
            return t

    @_(r'[-][-].*')
    def ONE_LINE_COMMENT(self, t):
        self.comm_line = True

    def salida(self, texto):
        list_strings = []
        # 注意这里应该用self.tokenize而不是全局的lexer
        for token in self.tokenize(texto):
            if self.comm_reg:
                continue
            elif self.comm_line:
                self.comm_line = False
                continue
            result = f'#{token.lineno} {token.type} '
            list_strings.append(result)
        return list_strings

关键提醒

global关键字仅用于访问模块级别定义的变量,类内部的属性(无论是类属性还是实例属性)都应该通过类名或self来访问,不要用global声明,否则会导致作用域混淆。

内容的提问来源于stack exchange,提问作者Jon Peña

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:12:51