Python class 属性 'is not defined' 当被另一个 class 属性引用时

Python class attribute 'is not defined' when referenced by another class attribute

使用以下内容,我能够成功创建解析器并通过 __init()__ 方法将我的参数添加到 self._parser

class Parser:
    _parser_params = {
        'description': 'Generate a version number from the version configuration file.',
        'allow_abbrev': False
    }
    _parser = argparse.ArgumentParser(**_parser_params)

现在我希望将参数分成组,所以我更新了我的模块,添加了一些 classes 来表示参数组(实际上 classes 有几个子 classes ArgumentGroup class), 并更新 Parser class.

class ArgumentGroup:
    _title = None
    _description = None

    def __init__(self, parser) -> ArgumentParser:
        parser.add_argument_group(*self._get_args())

    def _get_args(self) -> list:
        return [self._title, self._description]


class ArgumentGroup_BranchType(ArgumentGroup):
    _title = 'branch type arguments'


class Parser:
    _parser_params = {
        'description': 'Generate a version number from the version configuration file.',
        'allow_abbrev': False
    }
    _parser = argparse.ArgumentParser(**_parser_params)
    _argument_groups = [cls(_parser) for cls in ArgumentGroup.__subclasses__()]

但是,我现在看到一个错误。

Traceback (most recent call last):
  ...
  File "version2/args.py", line 62, in <listcomp>
    _argument_groups = [cls(_parser) for cls in ArgumentGroup.__subclasses__()]
NameError: name '_parser' is not defined

我不明白的是为什么 _parser_params 在被另一个 class 属性引用时确实存在,但 _parser 在同一场景中似乎不存在?我如何重构我的代码以根据需要添加解析器组?

这来自 Python 的两个怪癖:

  1. class 语句不创建新的局部作用域
  2. 列表理解创建一个新的本地范围。

因此,名称 _parser 在局部作用域中,其最近的封闭作用域是全局作用域,因此它不能引用 about-to-be class 属性。

一个简单的解决方法是用常规 for 循环替换列表理解。

_argument_groups = []
for cls in ArgumentGroup.__subclasses()__:
    _argument_groups.append(cls(_parser))

(更好的解决方案可能是在实例属性更有意义的地方停止使用 class 属性。)