je pourrais aller de toute façon à l'aide d'une seule grande méthode pour créer votre analyseur par rapport à prendre par étapes comme vous l'avez maintenant.
Je peux voir que vous avez défini quelques utilitaires auxiliaires utiles, tels que fente ("supprimer Literal", je présume), stringtolits, et decimaltable. Cela me semble bon. J'aime que vous utilisiez des noms de résultats, ils améliorent vraiment la robustesse de votre code post-analyse. Je recommande d'utiliser le formulaire raccourci qui a été ajouté dans pyparsing 1.4.7, dans lequel vous pouvez remplacer
busname.setResultsName("bus1")
avec
busname("bus1")
Cela peut désencombrer votre code un peu. Je regarderais en arrière dans vos actions d'analyse pour voir où vous utilisez des index numériques pour accéder aux jetons individuels, et revenir en arrière et assigner des noms de résultats à la place. Voici un cas, où GetStats renvoie (ngroup + sgroup).setParseAction(self.process_stats)
. process_stats a des références comme:
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"]
J'aime que vous avez Group'ed les valeurs et les statistiques, mais allez-y et leur donner des noms, comme « réseau » et « soln ». Ensuite, vous pouvez écrire ce code d'action d'analyse syntaxique comme (je l'ai aussi converti au - me - plus facile à lire la notation-attribut objet au lieu de la notation élément 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
En outre, une question de style: pourquoi utilisez-vous parfois le constructeur explicite And, au lieu d'utiliser l'opérateur '+'?
busdef = And([busname.setResultsName("bus1"),
busname.setResultsName("bus2"),
integer.setResultsName("linenum"),
decimaltable("pf qf pl ql".split())])
C'est tout aussi bien écrit:
busdef = (busname("bus1") + busname("bus2") +
integer("linenum") +
decimaltable("pf qf pl ql".split()))
Dans l'ensemble, je pense que cela est à propos par un fichier de cette complexité.J'ai un format similaire (propriétaire, malheureusement, ne peut donc pas être partagée) dans lequel je construit le code en morceaux similaires à la façon dont vous avez, mais dans une grande méthode, quelque chose comme ceci:
def parser():
header = Group(...)
inputsummary = Group(...)
jobstats = Group(...)
measurements = Group(...)
return header("hdr") + inputsummary("inputs") + jobstats("stats") + measurements("meas")
Les constructions du groupe sont particulièrement utiles dans un grand analyseur comme celui-ci, pour établir une sorte d'espace de noms pour les noms de résultats dans chaque section des données analysées.
Juste le genre de réponse que je cherchais. Le raccourci du nom rendra les choses plus belles. la notation d'objet-attribut est nouvelle pour moi; ça marche avec tous les dicts? de toute façon, merci. J'ai utilisé et parce que quand j'ai écrit ces parties j'ai oublié la continuation de la ligne implicite entre parenthèses. Je pense avoir PSATReport_IO en tant que classe séparée, il n'y a vraiment pas beaucoup d'autres fonctions qui sont nécessaires et il semble trop encombré. –
dd = dict (zip ("a b c d" .split(), plage (4))); dd.a; dd ["a"] Non, cela ne fonctionne pas. Bonne syntaxe cependant. Je pourrais avoir à essayer de l'implémenter dans une classe dict personnalisée. –
Non, le référencement de style d'attribut d'objet est une caractéristique de ParseResults de pyparsing, introuvable dans les dicts Python standard. Comme un point de données supplémentaire, mon analyseur pour le format propriétaire est d'environ 900 lignes. – PaulMcG