How to access fields with StrategyPattern in Python?
Question: I'm trying to use the Strategy Pattern to include different behaviours for
different sizes of a simulation.

I came across [this
implementation](http://codereview.stackexchange.com/questions/20718/strategy-
design-pattern-with-various-duck-type-classes) from the first example of the
book [Head First Design
Patterns](http://rads.stackoverflow.com/amzn/click/0596007124).

However, I don't understand where and how should I access my data initialised
in my simulation.

    
    
    from abc import ABCMeta, abstractmethod
    ###########################################################################    #####
    # Abstract Simulation class and concrete Simulation type classes.
    ################################################################################
    
    class Simulation:
        def __init__(self, run, plot):
            self._run_behavior = run
            self._plot_behavior = plot
    
        def run(self):
            return self._run_behavior.run()
    
        def plot(self):
            return self._plot_behavior.plot()        
    
    class SmallSimulation(Simulation):
        def __init__(self):
            Simulation.__init__(self, Run(), Plot())
            print "I'm a small simulation"
            self.data = 'Small Data'
    
    class BigSimulation(Simulation):
        def __init__(self):
            Simulation.__init__(self, Run(), Plot())
            print "I'm a big simulation"
            self.data = 'Big Data'
    
    class LargeSimulation(Simulation):
        def __init__(self):
            Simulation.__init__(self, RunLarge(), Plot())
            print "I'm a large simulation"
            self.data = 'Large Data'
    
    ################################################################################
    # Run behavior interface and behavior implementation classes.
    ################################################################################
    
    class RunBehavior:
        __metaclass__ = ABCMeta
        @abstractmethod 
        def run(self):
            pass
    
    class Run(RunBehavior):
        def run(self):
            print "I'm running standard"
            print self.data
    
    class RunLarge(RunBehavior):
        def run(self):
            print "I'm running multilevel"
    
    
    ################################################################################
    # Plot behavior interface and behavior implementation classes.
    ################################################################################
    
    class PlotBehavior:
        __metaclass__ = ABCMeta
        @abstractmethod 
        def plot(self):
            pass
    
    class Plot(PlotBehavior):
        def plot(self):
            print "I'm plotting results"
    
    ################################################################################
    # Test Code.
    ################################################################################
    
    if __name__ == '__main__':
        smallSimulation = SmallSimulation()
        bigSimulation = BigSimulation()
        largeSimulation = LargeSimulation()
    
        print('='*20)
        print('Execution')
        smallSimulation.run()
        bigSimulation.run()
        largeSimulation.run()
    
        print('='*20)
        print('Plotting')
        smallSimulation.plot()
        bigSimulation.plot()
        largeSimulation.plot()
    

The output is

    
    
    I'm a small simulation
    I'm a big simulation
    I'm a large simulation
    ====================
    Execution
    I'm running standard
    Traceback (most recent call last):
      File "strategy.py", line 84, in <module>
        smallSimulation.run()
      File "strategy.py", line 16, in run
        return self._run_behavior.run()
      File "strategy.py", line 52, in run
        print self.data
    AttributeError: 'Run' object has no attribute 'data'
    

How should I initialise and access my data?


Answer: Your run class doesn't have a data attribute, hence the exception.

    
    
    class Run(RunBehavior):
    # This class does NOT have a data attribute
        def run(self):
            print "I'm running standard"
            print self.data
    

To access simulation's `data` within `Run`, you can pass it in Run's init():

    
    
    class Run(RunBehavior):
        def __init__(self, data):
           self.data = data
        def run(self):
           print "I'm running standard"
           print self.data
    

