【问题标题】:How should I organise my functions with pyparsing?我应该如何使用 pyparsing 组织我的函数?
【发布时间】:2009-12-08 11:17:38
【问题描述】:

我正在用 python 和pyparsing 解析一个文件(这是 Matlab 中PSAT 的报告文件,但这并不重要)。 here 是我目前所拥有的。我认为这是一团糟,想就如何改进它提出一些建议。具体来说,我应该如何使用 pyparsing 组织我的语法定义?

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

我是否应该将所有输入和输出代码放在一个单独的文件中,以供其他类函数使用?这将使课堂的目的更加清晰。

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

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

【问题讨论】:

    标签: python refactoring coding-style pyparsing


    【解决方案1】:

    我可以选择使用单一的大方法来创建解析器,而不是像现在这样逐步进行。

    我可以看到您已经定义了一些有用的辅助实用程序,例如 slot(我猜是“suppress Literal”)、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"]
    

    我喜欢您对值和统计信息进行了分组,但请继续为它们命名,例如“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 构造在像这样的大型解析器中特别有用,可以为解析数据的每个部分中的结果名称建立一种命名空间。

    【讨论】:

    • 正是我正在寻找的那种答案。名称快捷方式将使事情看起来更好。对象属性符号对我来说是新的;它适用于所有字典吗?无论哪种方式,谢谢。我使用 and 因为当我写这些部分时,我忘记了括号内隐含的行延续。我正在考虑将 PSATReport_IO 作为一个单独的类,实际上不需要太多其他功能,而且看起来太杂乱了。
    • dd = dict(zip("a b c d".split(),range(4))); dd.a; dd["a"] 不,它不起作用。不过语法不错。我可能不得不尝试在自定义 dict 类中实现它。
    • 不,对象属性样式引用是 pyparsing 的 ParseResults 的一个功能,在标准 Python dicts 中找不到。作为一个额外的数据点,我的专有格式解析器长约 900 行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多