我应该如何用pyparsing组织我的功能?

时间:2009-12-08 11:17:39

标签: python refactoring coding-style pyparsing

我正在使用python和pyparsing解析文件(它是Matlab中PSAT的报告文件,但这并不重要)。 here是我到目前为止所拥有的。我认为这是一个烂摊子,并希望得到一些如何改善它的建议。具体来说,我应该如何用pyparsing组织我的语法定义?

我应该在一个函数中拥有所有语法定义吗?如果是这样,那将是一个巨大的功能。如果没有,那么我该如何分解呢。目前我已将其拆分为文件的各个部分。是否值得制作只能从一个地方调用一次的大量函数。对我来说,两者都没有。

我应该将所有输入和输出代码放在一个单独的文件中吗?这将使课堂的目的更加清晰。

我也有兴趣知道是否有更简单的方法来解析文件,进行一些健全性检查并将数据存储在类中。我似乎花了很多时间做这件事。

(如果人们同意,我会接受足够好使用X而不是pyparsing 的答案)

1 个答案:

答案 0 :(得分:2)

我可以使用一个大方法来创建解析器,而不是按照现在的方式执行它。

我可以看到你已经定义了一些有用的辅助工具,比如slit(“压缩文字”,我推测),stringtolits和decimaltable。这对我来说很好。

我喜欢您正在使用结果名称,它们确实提高了解析后代码的健壮性。我建议使用在pyparsing 1.4.7中添加的快捷方式表单,您可以在其中替换

busname.setResultsName("bus1")

busname("bus1")

这可以使您的代码完全消失。

我会回顾您的解析操作,看看您使用数字索引访问单个令牌的位置,然后返回并指定结果名称。这是一个案例,其中GetStats返回(ngroup + sgroup).setParseAction(self.process_stats)。 process_stats的引用如下:

self.num_load = tokens[0]["loads"]
self.num_generator = tokens[0]["generators"]
self.num_transformer = tokens[0]["transformers"]
self.num_line = tokens[0]["lines"]
self.num_bus = tokens[0]["buses"]
self.power_rate = tokens[1]["rate"]

我喜欢你有Group'ed的值和统计数据,但请继续给他们命名,比如“network”和“soln”。然后你可以编写这个解析动作代码(我也转换为 - 对我来说 - 更容易阅读的对象属性表示法而不是dict元素表示法):

self.num_load = tokens.network.loads
self.num_generator = tokens.network.generators
self.num_transformer = tokens.network.transformers
self.num_line = tokens.network.lines
self.num_bus = tokens.network.buses
self.power_rate = tokens.soln.rate

另外,一个样式问题:你为什么有时使用显式And构造函数,而不是使用'+'运算符?

busdef = And([busname.setResultsName("bus1"),
            busname.setResultsName("bus2"),
            integer.setResultsName("linenum"),
            decimaltable("pf qf pl ql".split())])

这很容易写:

busdef = (busname("bus1") + busname("bus2") + 
            integer("linenum") + 
            decimaltable("pf qf pl ql".split()))

总的来说,我认为这对于这种复杂性的文件而言是相同的。我有一个类似的格式(专有,不幸的是,所以无法共享),我在其中构建类似于你的方式的代码,但在一个大的方法,像这样:

def parser():
    header = Group(...)
    inputsummary = Group(...)
    jobstats = Group(...)
    measurements = Group(...)
    return header("hdr") + inputsummary("inputs") + jobstats("stats") + measurements("meas")

Group构造在这样的大型解析器中特别有用,可以为解析数据的每个部分中的结果名称建立一种命名空间。