0

I created many instances of a PlotHandler class. An instance must keep it's variables private. But the way I managed them led to a hard to detect problem, a private list variable is shared between instances! And that too without any obvious source for the leak.

My debugging told me that the private member function that modifies the list sees the same list, even if they are different objects.

Is this a "gotcha" problem? What is the best way to troubleshoot this?


Here are the relevant parts (I hope they are!) of the implementation. Please see the ALL-CAPS comments:

The file implementing PlotHandler:

class PlotHandler(wx.Frame):
    __crop_section = None
    __projection   = None
    __crop_xcord   = None

    _band_data     = [] #THIS GETS SHARED

def _on_plot_click(self, xcord): #CALLED BY ANOTHER OBJECT
    band = self._analyze_band( xcord )
    self._band_data.append(band)
    ...

The parent class that it is managing PlotHandlers:

class MainFrame(wx.Frame):
    __close_callback__ = None
    _plot_handlers     = []
    def __init__(self, parent, title):
        ...


    def InitUI(self):
        ...

        img_handler = ImageHandler(panel)
        self.img_src.register_callback( img_handler.update_image )

        #you need to call PlotHandler(parent, cropped)
        img_handler.register_sample_callback( self._create_new_plot_handler )

        ...

    def _create_new_plot_handler(self, cropped_sample ):
    self._plot_handlers.append( PlotHandler(self, cropped_sample) ) #CREATE THEM
Jesvin Jose
  • 22,498
  • 32
  • 109
  • 202

2 Answers2

3

See this question, this one, and tons of other stuff you can find by googling "Python class variables shared", "Python FAQ class variables", etc.

The short answer is: variables defined directly in the class body are class variables, not instance variables, and are thus shared among instances of the class. If you want instance variables you must assign them from within a method, where you have access to self.

Community
  • 1
  • 1
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • 1
    This is the clearest explanation: http://stackoverflow.com/questions/8860447/why-does-python-seem-to-treat-instance-variables-as-shared-between-objects . – Jesvin Jose Jun 15 '12 at 06:47
1

Class attributes are shared between instances. If you want to define an instance attribute (so each object have its own reference to the variable) you have to define it in __init__

class PlotHandler(wx.Frame):
    __crop_section = None
    __projection   = None
    __crop_xcord   = None

    def __init__(self, **kwargs):
        self._band_data = [] #THIS IS NOT SHARED
Diego Navarro
  • 9,316
  • 3
  • 26
  • 33