473,406 Members | 2,710 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

state machine and a global variable

Dear list,
I'm writing very simple state machine library, like this:

_state = None

def set_state(state):
global _state
_state = state

def get_state():
print _surface

but I hate to use global variable. So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:

from state_machine import *
set_state(3)
get_state()

I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()

Thanks, in advance!
Dec 14 '07 #1
11 1874
On Dec 14, 2007 10:52 AM, <tu*********@gmail.comwrote:
Dear list,
I'm writing very simple state machine library, like this:

_state = None

def set_state(state):
global _state
_state = state

def get_state():
print _surface

but I hate to use global variable. So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:
Yes, don't do it.
from state_machine import *
set_state(3)
get_state()
This isn't a state machine, it's just state
I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()
Stop being afraid of objects, especially if your fear is caused by
straw-man C style APIs.

from state_machine import State

state = State()
print state.current_state
state.do_something('sadfsafsad') #does something based on the current state
print state.current_state
Dec 14 '07 #2
On Dec 14, 8:52 am, tuom.lar...@gmail.com wrote:
Dear list,
I'm writing very simple state machine library, like this:

_state = None

def set_state(state):
global _state
_state = state

def get_state():
print _surface

but I hate to use global variable. So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:

from state_machine import *
set_state(3)
get_state()

I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()

Thanks, in advance!
Personally I _would_ do it the second way. That seems to be the most
appropriate way to do it. However, you can do it the second way and
still get the functionality you desire.
[code in state_machine.py]
class StateMachine(object):
def __init__(self, state=None):
if state is None:
state = "DEFAULT_INIT_STATE"
self._state = state

def get_state(self):
# print self._surface
return self._state

def set_state(self, state):
self._state = state

_sm = StateMachine()
set_state = _sm.set_state
get_state = _sm.get_state
[/code]

Matt
Dec 14 '07 #3
On Dec 14, 7:35 pm, Matimus <mccre...@gmail.comwrote:
On Dec 14, 8:52 am, tuom.lar...@gmail.com wrote:
Dear list,
I'm writing very simple state machine library, like this:
_state = None
def set_state(state):
global _state
_state = state
def get_state():
print _surface
but I hate to use global variable. So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:
from state_machine import *
set_state(3)
get_state()
I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()
Thanks, in advance!

Personally I _would_ do it the second way. That seems to be the most
appropriate way to do it. However, you can do it the second way and
still get the functionality you desire.

[code in state_machine.py]
class StateMachine(object):
def __init__(self, state=None):
if state is None:
state = "DEFAULT_INIT_STATE"
self._state = state

def get_state(self):
# print self._surface
return self._state

def set_state(self, state):
self._state = state

_sm = StateMachine()
set_state = _sm.set_state
get_state = _sm.get_state
[/code]

Matt

Thanks a lot! This is precisely what I had on my mind.
Dec 14 '07 #4
On Dec 14, 11:52 am, tuom.lar...@gmail.com wrote:
Dear list,
I'm writing very simple state machine library, like this:

_state = None

def set_state(state):
global _state
_state = state

def get_state():
print _surface

but I hate to use global variable. So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:

from state_machine import *
set_state(3)
get_state()

I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()

Thanks, in advance!
I would recommend you do it the long way, but then provide convenience
functions for users who'd prefer a simplified interface:

def set_state(x):
my_machine.set_state(x)

def set_state():
return my_machine.get_state()
Some users won't want the simplified interface. Really.
Carl Banks
Dec 14 '07 #5
tu*********@gmail.com a écrit :
Dear list,
I'm writing very simple state machine library, like this:

_state = None

def set_state(state):
global _state
_state = state

def get_state():
print _surface
NameError here !-)
>
but I hate to use global variable.
<aol />
So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:

from state_machine import *
set_state(3)
get_state()

I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()

A possible solution:

# state_machine.py
class _StateMachine(object):
def __init__(self):
self._state = SomethingHere()
def get_state(self):
return self._state
def set_state(self, xxx):
# etc

_s = _StateMachine()
get_state = _s.get_state()
set_state = _s.set_state()

You still have a global, but at least it's a machine instance, not it's
state !-)

Now the question is: why do you think it's so important for your users
to only see functions ? What's so wrong with:

from state_machine import *
m = get_state_machine()
m.set_state(42)
Dec 14 '07 #6
On Dec 14, 11:06 pm, Bruno Desthuilliers
<bdesth.quelquech...@free.quelquepart.frwrote:
tuom.lar...@gmail.com a écrit :
Dear list,
I'm writing very simple state machine library, like this:
_state = None
def set_state(state):
global _state
_state = state
def get_state():
print _surface

NameError here !-)
but I hate to use global variable.

<aol />
So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:
from state_machine import *
set_state(3)
get_state()
I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()

A possible solution:

# state_machine.py
class _StateMachine(object):
def __init__(self):
self._state = SomethingHere()
def get_state(self):
return self._state
def set_state(self, xxx):
# etc

_s = _StateMachine()
get_state = _s.get_state()
set_state = _s.set_state()
I guess you meant without the parentheses:
get_state = _s.get_state
set_state = _s.set_state

You still have a global, but at least it's a machine instance, not it's
state !-)

Now the question is: why do you think it's so important for your users
to only see functions ? What's so wrong with:

from state_machine import *
m = get_state_machine()
m.set_state(42)
Well, I guess I can see the advantages of using the class instances
but ... um ... the world isn't like that! :)

Consider this: how do you add up some numbers?
- "My sum is zero."
- "I add 3 to my sum."
- "I add 2 to my sum."

Or:
- "Three."
- "plus two."

Implicit context, some people call it. Sometimes it's useful to be as
precise as possible ("explicit is better than implict", right?) but
sometimes, it seems to me, it's just more natural not to repeat the
context all over again.

Thoughts?
Dec 14 '07 #7
On Dec 14, 2007 4:43 PM, <tu*********@gmail.comwrote:
On Dec 14, 11:06 pm, Bruno Desthuilliers
<bdesth.quelquech...@free.quelquepart.frwrote:
tuom.lar...@gmail.com a écrit :
Dear list,
I'm writing very simple state machine library, like this:
_state = None
def set_state(state):
global _state
_state = state
def get_state():
print _surface
NameError here !-)
but I hate to use global variable.
<aol />
So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:
from state_machine import *
set_state(3)
get_state()
I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()
A possible solution:

# state_machine.py
class _StateMachine(object):
def __init__(self):
self._state = SomethingHere()
def get_state(self):
return self._state
def set_state(self, xxx):
# etc

_s = _StateMachine()
get_state = _s.get_state()
set_state = _s.set_state()

I guess you meant without the parentheses:
get_state = _s.get_state
set_state = _s.set_state

You still have a global, but at least it's a machine instance, not it's
state !-)

Now the question is: why do you think it's so important for your users
to only see functions ? What's so wrong with:

from state_machine import *
m = get_state_machine()
m.set_state(42)

Well, I guess I can see the advantages of using the class instances
but ... um ... the world isn't like that! :)

Consider this: how do you add up some numbers?
- "My sum is zero."
- "I add 3 to my sum."
- "I add 2 to my sum."

Or:
- "Three."
- "plus two."

Implicit context, some people call it. Sometimes it's useful to be as
precise as possible ("explicit is better than implict", right?) but
sometimes, it seems to me, it's just more natural not to repeat the
context all over again.
You're way too hung up on context when you should be hung up on state.
Implicit state is bad, implicit global state is worse. You've got a
shared global state, with an interface that's designed to dispatch on
and mutate that state. It's basically every bad thing you can imagine
about global state. Using an object means that the state machine is
*local* state. Local state is good, because you've got a way to attach
a name to it, to manipulate it explicitly, and to pass it around to
other places.

Your example presupposes two different use cases anyway, but most
importantly what you're describing with sum is a mutation of local
state (a local name binding), which is a very different thing than
your state machine API.

Honestly, I can't even imagine why you would want to implement a state
machine *library* this way. If you meant "a library that has internal
state" it makes a little more sense - I use an approach kind of like
the one Bruno showed to handle global configuration and logging - but
if you meant "a library for implementing state machines" you're on
totally the wrong track.
Dec 14 '07 #8
On Dec 15, 12:02 am, "Chris Mellon" <arka...@gmail.comwrote:
On Dec 14, 2007 4:43 PM, <tuom.lar...@gmail.comwrote:
On Dec 14, 11:06 pm, Bruno Desthuilliers
<bdesth.quelquech...@free.quelquepart.frwrote:
tuom.lar...@gmail.com a écrit :
Dear list,
I'm writing very simple state machine library, like this:
_state = None
def set_state(state):
global _state
_state = state
def get_state():
print _surface
NameError here !-)
but I hate to use global variable.
<aol />
So, please, is there a better way
of doing this? All I want is that a user has to type as little as
possible, like:
from state_machine import *
set_state(3)
get_state()
I.e., nothing like:
import state_machine
my_machine = state_machine.new_machine()
my_machine.set_state(3)
my_machine.get_state()
A possible solution:
# state_machine.py
class _StateMachine(object):
def __init__(self):
self._state = SomethingHere()
def get_state(self):
return self._state
def set_state(self, xxx):
# etc
_s = _StateMachine()
get_state = _s.get_state()
set_state = _s.set_state()
I guess you meant without the parentheses:
get_state = _s.get_state
set_state = _s.set_state
You still have a global, but at least it's a machine instance, not it's
state !-)
Now the question is: why do you think it's so important for your users
to only see functions ? What's so wrong with:
from state_machine import *
m = get_state_machine()
m.set_state(42)
Well, I guess I can see the advantages of using the class instances
but ... um ... the world isn't like that! :)
Consider this: how do you add up some numbers?
- "My sum is zero."
- "I add 3 to my sum."
- "I add 2 to my sum."
Or:
- "Three."
- "plus two."
Implicit context, some people call it. Sometimes it's useful to be as
precise as possible ("explicit is better than implict", right?) but
sometimes, it seems to me, it's just more natural not to repeat the
context all over again.

You're way too hung up on context when you should be hung up on state.
Implicit state is bad, implicit global state is worse. You've got a
shared global state, with an interface that's designed to dispatch on
and mutate that state. It's basically every bad thing you can imagine
about global state. Using an object means that the state machine is
*local* state. Local state is good, because you've got a way to attach
a name to it, to manipulate it explicitly, and to pass it around to
other places.

Your example presupposes two different use cases anyway, but most
importantly what you're describing with sum is a mutation of local
state (a local name binding), which is a very different thing than
your state machine API.

Honestly, I can't even imagine why you would want to implement a state
machine *library* this way. If you meant "a library that has internal
state" it makes a little more sense - I use an approach kind of like
the one Bruno showed to handle global configuration and logging - but
if you meant "a library for implementing state machines" you're on
totally the wrong track.
Now, I very much *apologize*! I'm very sorry, I meant "a library that
has internal state", instead of "a library for implementing state
machines".

Basically, I agree that often the local state is much more useful. It
just seems to me that for some application it's an overkill. Like say,
for Turtle [1] (no jokes, please :) or PostScript [2].

[1] http://en.wikipedia.org/wiki/Logo_turtle
[2] http://en.wikipedia.org/wiki/PostScript
Dec 14 '07 #9
On Fri, 14 Dec 2007 23:06:28 +0100, Bruno Desthuilliers wrote:
Now the question is: why do you think it's so important for your users
to only see functions ? What's so wrong with:

from state_machine import *
m = get_state_machine()
m.set_state(42)
I can't speak for the "only" part, but it is sometimes really convenient
to have a set of *cough* convenience functions that do the simple stuff
for you. For example:

import random
random.random()

is much nicer for the simple cases than:

import random
prng = random.Random()
prng.random()

with the advantage that you can still instantiate your own instance if
you need/want to.

--
Steven.
Dec 15 '07 #10
On Dec 15, 1:50 am, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.auwrote:
On Fri, 14 Dec 2007 23:06:28 +0100, Bruno Desthuilliers wrote:
Now the question is: why do you think it's so important for your users
to only see functions ? What's so wrong with:
from state_machine import *
m = get_state_machine()
m.set_state(42)

I can't speak for the "only" part, but it is sometimes really convenient
to have a set of *cough* convenience functions that do the simple stuff
for you. For example:

import random
random.random()

is much nicer for the simple cases than:

import random
prng = random.Random()
prng.random()

with the advantage that you can still instantiate your own instance if
you need/want to.

--
Steven.
I agree, completely!

Ok, I think I'm going to provide both the simplified interface and the
class to instantiate. Thanks all!

Now suppose, this class looks like:

class StateMachine(object):
def __init__...
def function0...
def function1...
def function2...
...

up to many. And later in the library I would like to expose the
simplified interface as well:

_machine = StateMachine()
function0 = _machine.function0
function1 = _machine.function1
function2 = _machine.function2
....

Is there a way to do so in a programmatic way? Like:

_machine = StateMachine()
for function in {every function in _machine}:
function = _machine.function

Not that it's difficult to copy-paste some lines, I'm just curious and
maybe it would be a tiny bit easier to maintain the library.
Dec 15 '07 #11
On Sat, 15 Dec 2007 01:07:17 -0800, tuom.larsen wrote:

....
later in the library I would like to expose the
simplified interface as well:

_machine = StateMachine()
function0 = _machine.function0
function1 = _machine.function1
function2 = _machine.function2
...

Is there a way to do so in a programmatic way? Like:

_machine = StateMachine()
for function in {every function in _machine}:
function = _machine.function

Not that it's difficult to copy-paste some lines, I'm just curious and
maybe it would be a tiny bit easier to maintain the library.
You can say:

# Untested!
_machine = StateMachine()
from new import instancemethod
for name in _machine.__class__.__dict__:
if name.startswith('_'): continue
obj = getattr(_machine, name)
if type(obj) == instancemethod:
globals()[name] = obj
but that's likely to export a bunch of functions you don't actually want.
A better solution might be to create a class attribute containing the
names you DO want to export, and reject everything else:

class StateMachine(object):
_exportable = ['spam', 'eggs', 'parrot']
# function definitions go here

for name in _machine.__class__.__dict__:
if name in _machine._exportable:
globals()[name] = getattr(_machine, name)

--
Steven
Dec 15 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: James Wansley | last post by:
I am using C# for codebehind and ASP.Net for page code. I am using a databound ASPxGrid on a page that is databound in the codebehind. I have a single LinkButton on this page. When I click this...
5
by: tuxedo | last post by:
Hi, Gurus, I have two web forms frm1 and frm2. In frm1, I wrote session("StudentID")= textbox1.text in a button click event. And then, Response.redirect("...frm2") In frm2, Page_load event, I...
4
by: BB | last post by:
Hello all, I might be missing something here, but am trying to understand the difference between using application-level variables--i.e. Application("MyVar")--and global variables--i.e. public...
5
by: ASP.Confused | last post by:
As you can tell from my previous posts on this issue...I'm really confused :-/ I have a few ASP.NET web applications on my web host's "https" server. Our web host has a single "bin" folder for...
8
by: Vishwanathan Raman | last post by:
Hi I have a declared a static DataSet object SOBJ in Global.asax.I also have a localy defined DataSet LSOBJ in Global.asax which I am storing in Application State.Is there any technical...
4
by: Shawnk | last post by:
This post is intended to verify that true value semantics DO NOT EXIST for the Enum class (relative to boolean operations). If this is true then (thus and therefore) you can not design state...
67
by: Rui Maciel | last post by:
I've been delving into finite state machines and at this time it seems that the best way to implement them is through an intense use of the goto statement. Yet, everyone plus their granmother is...
7
by: The Cool Giraffe | last post by:
Usually, when i declare a method and a variable in the header file i go as follows. public: int number; void doSome (); Then, in the CPP-file i will define it as follows. int number;
2
by: qiooeer | last post by:
I want to know more about FSM,would you help me ? where is more details about this? Thanks
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.