Python état-conception d'une machine
Liées à cette Pile Dépassement de la question C de machine d'état de la conception), pourriez-vous Pile Dépassement de gens partagent votre Python de machine d'état des techniques de conception avec moi (et la communauté)?
Pour le moment, je vais pour un moteur basé sur les éléments suivants:
class TrackInfoHandler(object):
def __init__(self):
self._state="begin"
self._acc=""
## ================================== Event callbacks
def startElement(self, name, attrs):
self._dispatch(("startElement", name, attrs))
def characters(self, ch):
self._acc+=ch
def endElement(self, name):
self._dispatch(("endElement", self._acc))
self._acc=""
## ===================================
def _missingState(self, _event):
raise HandlerException("missing state(%s)" % self._state)
def _dispatch(self, event):
methodName="st_"+self._state
getattr(self, methodName, self._missingState)(event)
## =================================== State related callbacks
Mais je suis sûr qu'il ya des tonnes de façons d'aller à elle tout en tirant parti de Python dynamique de la nature (p. ex. dynamique dispatching).
Je suis, après les techniques de conception pour le "moteur" qui reçoit les "événements" et des "dépêches" à l'encontre de ceux basés sur "l'état" de la machine.
- Pour paraphraser Adam point, je pense que certaines des informations plus concrètes sur ce que vous essayez d'accomplir en aide.
- Orendorff: juste assez. J'ai mis à jour la question en conséquence.
Vous devez vous connecter pour publier un commentaire.
Je n'ai pas vraiment la question. Le État modèle de Conception est assez clair. Voir la Modèles de conception de livre.
Qui est assez fréquent que les passe-partout, Java, C++, Python (et je suis sûr que d'autres langues, aussi).
Si votre état de transition règles arrive d'être trivial, il y a quelques optimisations pour pousser la règle de transition lui-même dans la super-classe.
Noter que nous avons besoin d'avoir des références vers l'avant, si nous nous référons à des classes par leur nom, et l'utilisation
eval
de traduire un nom de classe à une classe réelle. L'alternative est de faire la transition règles de variables d'instance, au lieu de variables de classe et ensuite de créer les instances de toutes les classes sont définies.Dans certains cas, votre cas n'est pas aussi simple que de tester les objets de l'égalité, de façon plus générale règle de transition est d'utiliser une liste en fonction des paires d'objets.
Car les règles sont évaluées de manière séquentielle, ce qui permet à un "défaut" de la règle.
globals()[self.map[input]]()
(ou une dict comme {'S1': S1}) instead of eval? To further nitpick, it's redefining the built-in
suivant"AbstractState
pas de meilleur nom queSuperState
? Et vous n'avez pas de copie de la transition de l'état partie. Le livre laisse le passage ouvert et mentionne différents de mise en œuvre de variations (Contexte de la méthode avec grand si-sinon, votre mise en œuvre, ou de l'état transtion dict)En avril, 2009 de Python Magazine, j'ai écrit un article sur l'incorporation d'un État DSL dans Python, en utilisant pyparsing et imputil. Ce code vous permettra d'écrire le module de feux.pystate:
et le DSL compilateur de créer tous les Feux, Rouge, Jaune, et Vert des classes, et le bon état de transition méthodes. Code pourrait appeler ces classes en utilisant quelque chose comme ceci:
(Malheureusement, imputil a été abandonné en Python 3.)
Il est ce modèle de conception pour l'utilisation de décorateurs afin de mettre en œuvre des machines à états. À partir de la description sur la page:
Il y a un exemple de code sur la page (il est assez long donc je ne vais pas coller ici).
J'ai aussi n'a pas été heureux avec les options actuelles pour state_machines j'ai donc écrit le state_machine bibliothèque.
Vous pouvez l'installer en
pip install state_machine
et de l'utiliser comme ceci:Je pense que S. Lott réponse est une bien meilleure façon de mettre en œuvre une machine à état, mais si vous voulez continuer avec votre approche, à l'aide de
(state,event)
comme la clé de votredict
est mieux. La modification de votre code:Cela dépend probablement sur le degré de complexité de votre machine d'état est. Pour de simples machines d'état, un dict des dicts (des événements-clés de l'état-clés pour DFAs, ou des événements-clés de listes/jeux/n-uplets de l'état-clés pour les Fan) sera probablement la chose la plus simple à écrire et à comprendre.
Pour les plus complexes de l'état des machines, j'ai entendu de bonnes choses au sujet de SMC, qui permet de compiler déclarative de l'état de la machine descriptions de code dans une grande variété de langues, y compris Python.
Le code suivant est vraiment une solution simple. La seule partie intéressante est:
Toute la logique de chaque état est contenue dans une classe à part. L'état est modifié par le remplacement de la " __classe__ " de l'instance en cours d'exécution.
Résultat:
Je n'hésiterais pas à recommander l'application d'un tel bien connu motif de vous. Il suffit d'aller pour une implémentation open source comme les transitions et enveloppez-les d'une autre classe autour d'elle si vous avez besoin de fonctionnalités personnalisées. Dans ce post je vais expliquer pourquoi je préfère cette mise en œuvre et de ses caractéristiques.
Je pense que l'outil PySCXML besoins de plus près aussi.
Ce projet utilise la définition de W3C: L'état Graphique XML (SCXML): Machine d'État de la Notation pour le Contrôle de l'Abstraction
Actuellement, SCXML est un projet de travail; mais les chances sont assez élevées que c'est l'obtention d'une recommandation du W3C bientôt (c'est la 9e ébauche).
Un autre point intéressant à souligner, c'est qu'il y a un Apache Commons projet visant à créer et à maintenir un Java SCXML moteur capable d'exécuter une machine d'état défini à l'aide d'un SCXML document, tout en faisant abstraction de l'environnement interfaces...
Et pour certaines autres outils, le soutien de cette technologie dans le futur quand SCXML quitte son projet de statut...
Je ne pense pas à atteindre pour une machine à états finis pour le traitement XML. La manière habituelle pour ce faire, je pense, est d'utiliser une pile:
Pour chaque type d'élément, vous avez juste besoin d'une classe qui prend en charge la
addCharacters
,addElement
, etclose
méthodes.EDIT: À préciser, oui, je ne veux soutenir que des machines à états finis sont généralement la mauvaise réponse, que comme une technique de programmation, ils sont de la foutaise et vous devriez rester loin.
Il y a un peu de vraiment bien comprise, bien délimitées, les problèmes pour lesquels les Smqs sont une solution sympa.
lex
, par exemple, est quelque chose de bon.Cela dit, FSMs n'est généralement pas bien composer avec le changement. Supposons qu'un jour vous voulez ajouter un peu de l'état, peut-être un "avons-nous vu de l'élément X encore?" pavillon. Dans le code ci-dessus, vous ajoutez un attribut booléen à l'élément de classe et vous avez terminé. Dans une machine à état fini, on double le nombre d'états et de transitions.
Des problèmes qui nécessitent des états finis au premier abord très souvent évoluer pour exiger encore plus de l'état, comme peut-être un nombre, à quel point votre FSM régime est grillé, ou pire, de vous faire évoluer dans une sorte de généralisation de l'état de la machine, et à ce stade, vous êtes vraiment dans le pétrin. Le plus vous allez, plus vos règles commencent à agir comme code, mais le code dans un lent langage interprété que vous avez inventé que personne d'autre ne sait, pour qui il n'y a pas de débogueur et sans outils.
Autres projets connexes:
http://fsme.sourceforge.net/
https://code.google.com/p/visio2python/
Vous pouvez peindre l'état de la machine et ensuite l'utiliser dans votre code.
Voici une solution pour les "statefull objets", je suis venu avec, mais c'est plutôt inefficace pour votre usage prévu, parce que les modifications de l'état sont relativement chers. Toutefois, il peut bien fonctionner pour les objets qui changent d'état rarement ou faire l'objet que d'un délimitée nombre de changements d'état. L'avantage est qu'une fois que l'état est changé, il n'est pas redondant indirection.
J'ai posté une "demande de commentaires" ici.