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

Pyparsing中DelimitedList与Dict联用为何如此繁琐?

Pyparsing:分隔列表转字典的简洁写法?

背景:DelimitedList与Dict的基础用法

Pyparsing提供ParseElementEnhance的子类DelimitedList,用于解析(通常是逗号分隔的)列表:

>>> kv_element = pp.Word(pp.alphanums)
>>> kv_list = pp.DelimitedList(kv_element)
>>> kv_list.parse_string('red, green, blue')
ParseResults(['red', 'green', 'blue'], {})

同时它还提供TokenConverter的子类Dict,可将重复表达式转换为字典:

>>> key = value = pp.Word(pp.alphanums)
>>> kv_pair = key + pp.Suppress("=") + value
>>> kv_dict = pp.Dict(pp.Group(kv_pair)[...])
>>> kv_dict.parse_string('R=red G=green B=blue')
ParseResults([
  ParseResults(['R', 'red'], {}),
  ParseResults(['G', 'green'], {}),
  ParseResults(['B', 'blue'], {})
], {'R': 'red', 'G': 'green', 'B': 'blue'})

问题:结合二者的繁琐之处

但将这两个类结合使用时,写法会变得十分繁琐。虽然能构建出从分隔列表解析字典的ParserElement,但相比单独使用要多做两步:

  • 重新定义DelimitedList,让它输出Group()包裹的结果
  • 构造Dict()时要重复DelimitedList的定义,才能通过类型检查1

示例代码:

>>> kv_pair = key + pp.Suppress("=") + value
>>> kv_pairlist = pp.DelimitedList(pp.Group(kv_pair))
>>> kv_pairdict = pp.Dict(kv_pairlist[...])
>>> kv_pairdict.parse_string('R=red, G=green, B=blue')
ParseResults([
  ParseResults(['R', 'red'], {}), 
  ParseResults(['G', 'green'], {}), 
  ParseResults(['B', 'blue'], {})
], {'R': 'red', 'G': 'green', 'B': 'blue'})

这种写法感觉像是在定义一个解析器,从一系列单元素分隔列表(每个列表包含一个键值对)中创建字典(我不确定内部是否真的如此运作)。

当我想表达“匹配一个包含多组键值对的分隔列表”这个意图时,总感觉是在和API较劲。更气人的是,kv_pairdict = pp.Dict(kv_pairlist)在功能上和上面的代码完全一致,但会触发类型检查错误。

提问

在Pyparsing的API里,有没有更简洁的方式来定义这个解析器?如果没有,这是我的设计思路有问题、Pyparsing的API存在不足,还是其他原因?

(是不是我搞反了定义顺序?DelimitedList(Dict(Group(kv_pair)[1, ...]))也能运行,但在我看来逻辑是颠倒的。不过这种写法几乎不需要和API较劲,难道是我的理解错了?)


注释

  1. (否则,至少在VSCode中会弹出如下不合理的提示:)

No overload variant of "dict" matches argument type
"DelimitedList" (mypycall-overload)

Possible overload variants:

def [_KT, _VT] __init__(self) -> dict[_KT, _VT]
    def [_KT, _VT] __init__(self, **kwargs: _VT) -> dict[str, _VT]
    def [_KT, _VT] __init__(self, SupportsKeysAndGetItem[_KT, _VT], /) -> dict[_KT, _VT]
    def [_KT, _VT] __init__(self, SupportsKeysAndGetItem[str, _VT], /, **kwargs: _VT) -> dict[str, _VT]
    def [_KT, _VT] __init__(self, Iterable[tuple[_KT, _VT]], /) -> dict[_KT, _VT]
    def [_KT, _VT] __init__(self, Iterable[tuple[str, _VT]], /, **kwargs: _VT) -> dict[str, _VT]
    def [_KT, _VT] __init__(self, Iterable[list[str]], /) -> dict[str, str]
    def [_KT, _VT] __init__(self, Iterable[list[bytes]], /) -> dict[bytes, bytes]mypy(note)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:29:50