Re: State Machines in Python

Discussion in 'Python' started by D'Arcy J.M. Cain, Sep 4, 2010.

  1. On Sat, 4 Sep 2010 14:36:38 +0100
    Jack Keegan <> wrote:
    > Just joined the group. I'm new to Python but been picking it up pretty easy.


    Welcome aboard.

    > As there is no switch statement in Python, I've been looking around for a
    > good implementation. Most of the algorithms I've come across seem to be


    There's no switch statement because there's no real need for one.
    Check out the following sample code and see if it gives you some ideas.

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-

    # Sample state machine

    import sys

    data = dict(counter = 0, flag = False)

    def state1(d):
    d['counter'] += 1
    print "In state 1, counter = %(counter)d" % d
    if d['flag']: sys.exit(0)
    return state2

    def state2(d):
    d['counter'] += 1
    print "In state 2, counter = %(counter)d" % d
    return state3

    def state3(d):
    d['counter'] += 1
    d['flag'] = True
    print "In state 3, counter = %(counter)d" % d
    return state1

    state = state1
    while True:
    state = state(data)


    --
    D'Arcy J.M. Cain <> | Democracy is three wolves
    http://www.druid.net/darcy/ | and a sheep voting on
    +1 416 425 1212 (DoD#0082) (eNTP) | what's for dinner.
     
    D'Arcy J.M. Cain, Sep 4, 2010
    #1
    1. Advertising

  2. D'Arcy J.M. Cain

    Roy Smith Guest

    In article <>,
    "D'Arcy J.M. Cain" <> wrote:

    > On Sat, 4 Sep 2010 14:36:38 +0100
    > Jack Keegan <> wrote:
    > > Just joined the group. I'm new to Python but been picking it up pretty easy.

    >
    > Welcome aboard.
    >
    > > As there is no switch statement in Python, I've been looking around for a
    > > good implementation. Most of the algorithms I've come across seem to be

    >
    > There's no switch statement because there's no real need for one.
    > Check out the following sample code and see if it gives you some ideas.
    >
    > #! /usr/bin/env python
    > # -*- coding: utf-8 -*-
    >
    > # Sample state machine
    >
    > import sys
    >
    > data = dict(counter = 0, flag = False)
    >
    > def state1(d):
    > d['counter'] += 1
    > print "In state 1, counter = %(counter)d" % d
    > if d['flag']: sys.exit(0)
    > return state2
    >
    > def state2(d):
    > d['counter'] += 1
    > print "In state 2, counter = %(counter)d" % d
    > return state3
    >
    > def state3(d):
    > d['counter'] += 1
    > d['flag'] = True
    > print "In state 3, counter = %(counter)d" % d
    > return state1
    >
    > state = state1
    > while True:
    > state = state(data)


    This is the pattern I've always used. Simple and effective for any
    state machine which is small enough to code by hand. I generally have
    my state methods return (next_state, output) tuples, but that's a detail.
     
    Roy Smith, Sep 4, 2010
    #2
    1. Advertising

  3. D'Arcy J.M. Cain

    MRAB Guest

    On 04/09/2010 18:58, Roy Smith wrote:
    > In article<>,
    > "D'Arcy J.M. Cain"<> wrote:
    >
    >> On Sat, 4 Sep 2010 14:36:38 +0100
    >> Jack Keegan<> wrote:
    >>> Just joined the group. I'm new to Python but been picking it up pretty easy.

    >>
    >> Welcome aboard.
    >>
    >>> As there is no switch statement in Python, I've been looking around for a
    >>> good implementation. Most of the algorithms I've come across seem to be

    >>
    >> There's no switch statement because there's no real need for one.
    >> Check out the following sample code and see if it gives you some ideas.
    >>
    >> #! /usr/bin/env python
    >> # -*- coding: utf-8 -*-
    >>
    >> # Sample state machine
    >>
    >> import sys
    >>
    >> data = dict(counter = 0, flag = False)
    >>
    >> def state1(d):
    >> d['counter'] += 1
    >> print "In state 1, counter = %(counter)d" % d
    >> if d['flag']: sys.exit(0)
    >> return state2
    >>
    >> def state2(d):
    >> d['counter'] += 1
    >> print "In state 2, counter = %(counter)d" % d
    >> return state3
    >>
    >> def state3(d):
    >> d['counter'] += 1
    >> d['flag'] = True
    >> print "In state 3, counter = %(counter)d" % d
    >> return state1
    >>
    >> state = state1
    >> while True:
    >> state = state(data)

    >
    > This is the pattern I've always used. Simple and effective for any
    > state machine which is small enough to code by hand. I generally have
    > my state methods return (next_state, output) tuples, but that's a detail.


    I suppose that if they are that similar then you could generate the
    code from a list or table of the states.
     
    MRAB, Sep 4, 2010
    #3
  4. On Sat, 04 Sep 2010 13:58:00 -0400
    Roy Smith <> wrote:
    > > while True:
    > > state = state(data)

    >
    > This is the pattern I've always used. Simple and effective for any
    > state machine which is small enough to code by hand. I generally have
    > my state methods return (next_state, output) tuples, but that's a detail.


    What is "output" for? Is it a string or something else? What do you
    do with it? Notice that I create a dictionary which is passed around
    so that states can pass whatever information back that they deem useful
    and any state can pick up whatever info it needs. for example, in my
    sample code every state uses the counter but only two states use the
    flag element.

    --
    D'Arcy J.M. Cain <> | Democracy is three wolves
    http://www.druid.net/darcy/ | and a sheep voting on
    +1 416 425 1212 (DoD#0082) (eNTP) | what's for dinner.
     
    D'Arcy J.M. Cain, Sep 4, 2010
    #4
  5. On Sat, 04 Sep 2010 19:13:28 +0100
    MRAB <> wrote:
    > I suppose that if they are that similar then you could generate the
    > code from a list or table of the states.


    They generally aren't as simple as the little example script that I
    cobbled together.

    --
    D'Arcy J.M. Cain <> | Democracy is three wolves
    http://www.druid.net/darcy/ | and a sheep voting on
    +1 416 425 1212 (DoD#0082) (eNTP) | what's for dinner.
     
    D'Arcy J.M. Cain, Sep 4, 2010
    #5
  6. D'Arcy J.M. Cain, 04.09.2010 20:30:
    > On Sat, 04 Sep 2010 13:58:00 -0400
    > Roy Smith<> wrote:
    >>> while True:
    >>> state = state(data)

    >>
    >> This is the pattern I've always used. Simple and effective for any
    >> state machine which is small enough to code by hand. I generally have
    >> my state methods return (next_state, output) tuples, but that's a detail.

    >
    > What is "output" for? Is it a string or something else? What do you
    > do with it? Notice that I create a dictionary which is passed around
    > so that states can pass whatever information back that they deem useful
    > and any state can pick up whatever info it needs. for example, in my
    > sample code every state uses the counter but only two states use the
    > flag element.


    I guess the idea is that each of the states can't arbitrarily modify the
    global status (dict) but is restricted to designating a next state and
    returning something. So you don't take the risk of introducing side effects
    somewhere because all state implementations are pure functions (at least as
    far as the state machine itself is concerned).

    Stefan
     
    Stefan Behnel, Sep 4, 2010
    #6
  7. D'Arcy J.M. Cain

    Roy Smith Guest

    In article <>,
    "D'Arcy J.M. Cain" <> wrote:

    > On Sat, 04 Sep 2010 13:58:00 -0400
    > Roy Smith <> wrote:
    > > > while True:
    > > > state = state(data)

    > >
    > > This is the pattern I've always used. Simple and effective for any
    > > state machine which is small enough to code by hand. I generally have
    > > my state methods return (next_state, output) tuples, but that's a detail.

    >
    > What is "output" for? Is it a string or something else?


    I've often used this pattern for parsing a text file and extracting
    interesting data. At various points during the input stream, you will
    have read an entire piece of data, and return it as the output of the
    state machine. Not every state will result in output being produced.

    As a trivial example, let's say I had a file format which stored network
    addresses in a deliberately silly style:

    --------------------
    # This is a comment

    host = 10.2.3.4
    port = 999
    proto = TCP

    port = 1001
    proto = TCP
    host = 192.168.1.1

    status = ignore
    host = 1.2.3.4
    port = 22
    host = 127.0.0.1

    proto = UDP
    port = 1001
    host = 192.168.1.1
    --------------------

    I want to parse out (host, port, proto) triples, i.e. the state machine
    should produce the following output:

    (10.2.3.4, 9099, TCP)
    (192.168.1.1, 1001, TCP)
    (192.168.1.1, 1001, UDP)

    As the end of each data block is recognized, a 3-tuple would be
    returned. Other state transitions would return None as the output.
    Then, the main loop can be something like:

    state = start
    for line in input:
    next_state, output = state(line)
    if output:
    print output
    state = next_state

    I'm not saying it has to be done that way, just that I've found it a
    handy pattern for the stuff I've done.
     
    Roy Smith, Sep 4, 2010
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sidney Cadot
    Replies:
    0
    Views:
    2,368
    Sidney Cadot
    Apr 18, 2004
  2. Steve

    Generics and state machines

    Steve, May 3, 2004, in forum: VHDL
    Replies:
    7
    Views:
    622
    Andreas Hinze
    May 5, 2004
  3. Clyde R. Shappee

    One-hot Coding of State machines

    Clyde R. Shappee, Jun 2, 2004, in forum: VHDL
    Replies:
    10
    Views:
    6,316
    Wallclimber
    Jun 3, 2004
  4. Martin Maurer
    Replies:
    3
    Views:
    668
    Andrew Hall
    Jun 14, 2004
  5. Leonard J. Reder

    Multithreaded Python FSM (Harel State Machines)

    Leonard J. Reder, Jun 9, 2005, in forum: Python
    Replies:
    3
    Views:
    855
    Leonard J. Reder
    Jun 18, 2005
Loading...

Share This Page