0

My code is composed of a queue thread class (called MyThread), a class inheriting MyThread (Device) and many class inheriting Device (such as A, B, ...)

Device instantiate a FSM (state machine). So each Device (A, B,..) have the same FSM table.

Now I am trying to implement callbacks of the FSM for/in each device A, B, ...

Here is a sketch of my code:

1.Device module:

MAP = {
'initial' : 'none',
'events': [
    {'name': 'load', 'src': ['OFF', 'ON', 'none'], 'dst': 'LOADED'},
    ],
 'callbacks': {}
}
class Device(MyThread):
    def __init__(self, actor=None):
        MyThread.__init__(self, actor, self.__class__)
        self.MAP =MAP
        self.MAP['callbacks']['onload'] = lambda e: self.initialise()
        self.start()
    def startFSM(self):
        self.started = True
        self.fsm = Fysom(self.MAP)
        self.fsm.startup()

2.MyThread module:

class MyThread(threading.Thread):
    def __init__(self, actor, name):
        threading.Thread.__init__(self, name=name)
        self.actor = actor
    def run(self):
        pass

3.A:

class A(Device):    
    def __init__(self, actor=None):
        Device.__init__(self, actor)
        self.status = None
    def initialise(self):
        print "Here is A"

4.B:

class B(Device):    
    def __init__(self, actor=None):
        Device.__init__(self, actor)
        self.status = None
    def initialise(self):
        print "Here is B"

Current code simplified:

a = A()
b = B()
a.fsm.load()
b.fsm.load()

which will returns :

Here is B
Here is B

instead of :

Here is A
Here is B

or again: a.MAP['callbacks']['onload'] has same memory location as b.MAP['callbacks']['onload']

The point here is to focus on MAP attributes. The issue is that the function saved in self.MAP['callbacks']['onload'] override the last one. But basically they should have one MAP per Device (A, B, ...). And each device should save is own initialise method into his own MAP attribute.

1 Answer 1

4

The problem is here:

MAP = {
'initial' : 'none',
'events': [
    {'name': 'load', 'src': ['OFF', 'ON', 'none'], 'dst': 'LOADED'},
    ],
 'callbacks': {}
}
class Device(MyThread):
    def __init__(self, actor=None):
        MyThread.__init__(self, actor, self.__class__)
        self.MAP =MAP  # Problem!

You're makingself.MAP a reference to MAP. So every instance of a class that inherits from Device ends up with a self.MAP property that's a reference to the exact same dict (the global MAP dict). What you really want is this, so that each instance gets its own dict:

from copy import deepcopy

MAP = {
'initial' : 'none',
'events': [
    {'name': 'load', 'src': ['OFF', 'ON', 'none'], 'dst': 'LOADED'},
    ],
 'callbacks': {}
}
class Device(MyThread):
    def __init__(self, actor=None):
        MyThread.__init__(self, actor, self.__class__)
        self.MAP = deepcopy(MAP)  # Make sure each MAP is unique.
Sign up to request clarification or add additional context in comments.

5 Comments

I think you would need to make a deep copy of the MAP dictionary otherwise the copies made will share elements -- many of which are containers themselves. Another possibility might to make a Map class and create new instances of it for each Device.
@mertineau Yes, you're right. I'll update the answer.
ty for help. I tried it but nothing changed. if for example I do a.MAP['callbacks']['onload'] = 0 it will also overrides b.MAP['callbacks']['onload']. I am wondering if it's not due to polymorphisme.
@Katsu I just updated the answer, I overlooked that MAP.copy() was only doing a shallow copy of the MAP. It changed the example to use deepcopy() which should fix the issue.
@dano&mertineau: Nice you are genious

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.