为什么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.7
(pyparsing
(GitHub repository) has been significantly restructured from a single module to a package, notably in commit 0b398062710dc00b952636bcf7b7933f74f125da)的当前开发版本。
关于 class ParseResults
的一些版本相关注释,用于表示每个解析器的结果:
- 在
pyparsing == 2.4.7
的源代码中,class ParserResults
位于 pyparsing.ParserResults
:https://github.com/pyparsing/pyparsing/blob/pyparsing_2.4.7/pyparsing.py#L502-L1207
- class
ParserResults
的新版本在模块pyparsing.results
中:https://github.com/pyparsing/pyparsing/blob/d27fd7627f3ed60b3b7a9e9f5e790d0e49107359/pyparsing/results.py#L27-L82
- 旧版本的代码已复制到
pyparsing
存储库顶层目录中的模块 pyparsing_archive
,并且似乎未被使用(例如,安装或导入)。所以 class ParserResults
的旧版本现在位于:https://github.com/pyparsing/pyparsing/blob/d27fd7627f3ed60b3b7a9e9f5e790d0e49107359/pyparsing_archive.py#L599-L1249
我正在尝试从 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.7
(pyparsing
(GitHub repository) has been significantly restructured from a single module to a package, notably in commit 0b398062710dc00b952636bcf7b7933f74f125da)的当前开发版本。
关于 class ParseResults
的一些版本相关注释,用于表示每个解析器的结果:
- 在
pyparsing == 2.4.7
的源代码中,classParserResults
位于pyparsing.ParserResults
:https://github.com/pyparsing/pyparsing/blob/pyparsing_2.4.7/pyparsing.py#L502-L1207 - class
ParserResults
的新版本在模块pyparsing.results
中:https://github.com/pyparsing/pyparsing/blob/d27fd7627f3ed60b3b7a9e9f5e790d0e49107359/pyparsing/results.py#L27-L82 - 旧版本的代码已复制到
pyparsing
存储库顶层目录中的模块pyparsing_archive
,并且似乎未被使用(例如,安装或导入)。所以 classParserResults
的旧版本现在位于:https://github.com/pyparsing/pyparsing/blob/d27fd7627f3ed60b3b7a9e9f5e790d0e49107359/pyparsing_archive.py#L599-L1249