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
6
  • _band_data is a class attribute, it's normal that it's shared between instances. Commented Jun 15, 2012 at 6:36
  • Normal behavior? Please elaborate? Commented Jun 15, 2012 at 6:37
  • Move it into your initializer, problem solved. Commented Jun 15, 2012 at 6:38
  • 1
    @aitchnyu : please don't take this as a personnal offense, but your problem comes from assuming that language X (here Python) works just like languages Y and Z, instead of actually reading the doc / doing the tutorial. Commented Jun 15, 2012 at 9:34
  • @bruno I thought I had learned about classes a year back. And the stars were aligned wrong only today, when I came across this issue. Commented Jun 15, 2012 at 9:50

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is the clearest explanation: stackoverflow.com/questions/8860447/… .
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

Comments

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.