2
\$\begingroup\$

This question is related to this topic.

Context:

class OperationDevice(Device):
    def __init__(self):
        super(OperationDevice, self).__init__()

    def operation_start(self):
        # Do operation specific code
        self.start()

    def operation_stop(self):
        # Do operation specific code
        self.stop()


class SimulationDevice(Device):
    def __init__(self):
        super(SimulationDevice, self).__init__()

    def simulation_start(self):
        # Do simulation specific code
        self.fsm.start()

    def simulation_stop(self):
        # Do simulation specific code
        self.fsm.stop()


class DualModeDevice(OperationDevice, SimulationDevice):
    def __init__(self, mode='simulation'):
        super(DualModeDevice, self).__init__()
        self._mode = mode
        self._start_map = {
            'simulation': self.simulation_start,
            'operation': self.operation_start
        }
        self._stop_map = {
            'simulation': self.simulation_stop,
            'operation': self.operation_stop
        }

    def start(self):
        self._start_map[self._mode]()

    def stop(self):
        self._stop_map[self._mode]()

Here I have to define in OperationDevice and SimulationDevice different method name like simulation_start and operation_start (because of MRO).

  • I actually want to define the same method name for both class and be able to call each one from DualModeDevice or subclasses. For example operation_start from OperationDevice and simulation_start from SimulationDevice will become start. Is it possible and how?

  • This solution is a way to switch between class OperationDevice and SimulationDevice following value of mode. I am wondering wether is it possible to define automatically all method from SimulationDevice linked with mode = "simulation" (same for OperationDevice with "operation") without having to specify for each method (self._start_map for example) in constructor (init) of DualModeDevice.

\$\endgroup\$

3 Answers 3

4
\$\begingroup\$

You could use composition instead of inheritance:

class OperationDevice(Device):
    def __init__(self):
        super(OperationDevice, self).__init__()

    def start(self):
        # Do operation specific code

    def stop(self):
        # Do operation specific code


class SimulationDevice(Device):
    def __init__(self):
        super(SimulationDevice, self).__init__()

    def start(self):
        # Do simulation specific code
        self.fsm.start()

    def stop(self):
        # Do simulation specific code
        self.fsm.stop()


class DualModeDevice(Device):
    def __init__(self, mode='simulation'):
        super(DualModeDevice, self).__init__()
        self._mode = mode
        self._mode_map = {
            'simulation': SimulationDevice(),
            'operation': OperationDevice()
        }

    def start(self):
        self._mode_map[self._mode].start()

    def stop(self):
        self._mode_map[self._mode].stop()
\$\endgroup\$
4
  • \$\begingroup\$ Ty you almost answered my question (+1). I want also to remove start and stop in DualModeDevice by using __getattribute__(self, name): getattr(self._mode_map[self._mode], name). But it calls method from Device class. Is it possible to update answer with __getattr__ method instead of start and stop? Ty again \$\endgroup\$
    – Katsu
    Jun 3, 2014 at 7:33
  • \$\begingroup\$ @Katsu Such magic can make code hard to follow. I'd rather live with some boilerplate code. \$\endgroup\$ Jun 3, 2014 at 8:57
  • \$\begingroup\$ @JanneKarila well ok I created a dedicated post for this). Now do you think is it necessary to keep inheritance between DualModeDevice and Device since there is composition? \$\endgroup\$
    – Katsu
    Jun 3, 2014 at 9:03
  • \$\begingroup\$ @Katsu No, unless there is something else that the classes could share via inheritance. \$\endgroup\$ Jun 3, 2014 at 9:27
2
\$\begingroup\$

I am wondering wether is it possible to define automatically all method from SimulationDevice linked with mode = "simulation" (same for OperationDevice with "operation") without having to specify for each method (self._start_map for example) in constructor (init) of DualModeDevice.

You could do this using __getattribute__. Something like:

def __getattribute__(self, name):
    if name in methods_to_map:
        return getattr(self.handler, name)
    return super(...).__getattribute__(name)

You would list the method names that you want to map based on mode in methods_to_map (as strings). Then you would set handler to the class implementing the current mode. E.g. self.mode = 'simulation' -> self.handler = SimulationDevice.

\$\endgroup\$
1
  • \$\begingroup\$ Ty for help. Is it possible to get more details about setting handler to the class because here DualDeviceMode derivate both class? \$\endgroup\$
    – Katsu
    Jun 2, 2014 at 14:35
2
\$\begingroup\$

You could map the individual parent to a specific mode in you maps as such:

class DualModeDevice(OperationDevice, SimulationDevice):
    def __init__(self, mode='simulation'):
        super(DualModeDevice, self).__init__()
        self._mode = mode
        self._mode_map = {
            'simulation': SimulationDevice,
            'operation': OperationDevice
        }

Then in your DualModeDevice methods do call those functions, passing in self:

def start(self):
    self._mode_map[self._mode].start(self)
\$\endgroup\$
1
  • \$\begingroup\$ Ty same comment as above (+1). \$\endgroup\$
    – Katsu
    Jun 3, 2014 at 7:35

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.