为什么pyparsing的可选总是return一个列表

Why does pyparsing's optional always return a list

我正在尝试从 SQL 语句中获取 LIMIT

query = "LIMIT 1"

LIMIT = "LIMIT"

int_num = pyparsing_common.signed_integer()

limit_clause = Optional(Group(LIMIT + int_num), None)
statement = limit_clause("limit")


if __name__ == "__main__":
    result = statement.parseString(query)
    print(result["limit"])

打印[['LIMIT', 1]]

这当然是一个人为的例子,但为什么 return 像 [['LIMIT', 1]] 而不仅仅是 1?有没有办法让它变成 return a 1?

根据pyparsing的文档:

  • 运算符 + 是一个 Expression operator,它“使用运算符前后的表达式创建 And”,
  • class And 是一个 Expression subclass,它“使用 ParserElements 列表构建,所有这些都必须与 And 匹配”,
  • class Group 是一个 special subclass ,它“使匹配的标记包含在列表中”,
  • class Optional 是一个 Expression subclass,它“用 ParserElement 构造,但不需要匹配该元素;可以用可选的 default 构造参数,...”。

因此,+ 运算符大致创建了一个结果列表 'LIMIT'pyparsing.pyparsing_common.signed_integer(),然后 class Group 创建了一个包含此结果的列表列表。这解释了为什么 'LIMIT'1 都出现在结果中,以及为什么它们在嵌套列表中。

实际情况稍微复杂一些,因为返回的对象不是 list,而是 class pyparsing.ParseResults 的实例。 运行 以下代码:

import pyparsing

# construct parser
LIMIT = 'LIMIT'
int_num = pyparsing.pyparsing_common.signed_integer()
limit_clause = pyparsing.Optional(pyparsing.Group(LIMIT + int_num), None)
statement = limit_clause('limit')
# parse a string
query = 'LIMIT 1'
result = statement.parseString(query)
print(repr(result))

打印:

([(['LIMIT', 1], {})], {'limit': [([(['LIMIT', 1], {})], {})]})

然后语句 print(repr(result['limit'])) 打印:

([(['LIMIT', 1], {})], {})

语句 print(str(result['limit'])) 打印:

[['LIMIT', 1]]

对于后代,这个答案使用pyparsing == 2.4.7pyparsingGitHub repository) has been significantly restructured from a single module to a package, notably in commit 0b398062710dc00b952636bcf7b7933f74f125da)的当前开发版本。

关于 class ParseResults 的一些版本相关注释,用于表示每个解析器的结果: