3

I was doing some work in Python when I ran into an unexpected problem. I have a class, and two variables x and y. x and y are meant to be separate copies of the class each with their own data. So I set x equal to the class and give it some values, then do the same with y. Once I try to use that data though, I realize that I overwrote my values for x. It seems that I have not created two separate copies of the class to work with but instead two references to the same class. So here is the general example in code:

x = someClass()
x.set(2, 0)
y = someClass()
y.set(3, 0)
print(x)

The end result is that 3 is printed instead of 2. I want to create a separate "version" of the class to hold different data for each variable. Not sure as to how though. Using Python 3.3. Here is the code for the class:

class someClass:
    def __init__(self, list = [0,0,0,0,0,0,0,0,0,0]):
        self.list = list
    def __repr__(self):
        return str(self.list)
    def set(self, loc, val):
        if ((loc >= 0) & (loc <= 9)):
            self.list[loc] = val
Iguananaut
  • 21,810
  • 5
  • 50
  • 63
Spino Prime
  • 108
  • 1
  • 1
  • 11
  • 2
    It looks like your problem is in the class definition ... can you post it? – Zero Piraeus Nov 14 '12 at 23:43
  • 3
    You're confusing classes and objects. When you call `someClass()` you create an instance of that class. That instance is (most likely) not itself a class. When you wrote 'I want to create a separate "version" of the class to hold different data' the terminology you were groping toward was that you want to create independent instances of class. Which you have. But you've somehow linked their data together. Beyond that it's hard to help without seeing some example code. – Iguananaut Nov 14 '12 at 23:43
  • without the definition of `someClass`, its `__init__` and `set` methods this question is impossible to answer. – msw Nov 14 '12 at 23:44
  • Most likely, you are assigning to a class variable (which is shared between instances of the class). You need to define instance variables. – Joel Cornett Nov 14 '12 at 23:44
  • Hard to answer without the class definition – Eudis Duran Nov 14 '12 at 23:47
  • I added the class definition stuff. Hope it helps. – Spino Prime Nov 14 '12 at 23:52
  • This `if ((loc >= 0) & (loc <= 9)):` is not doing what you think it does. This is `bitwise` AND in python. You need to replace `&` with `and` in order to do a *logical* AND. – rantanplan Nov 15 '12 at 00:09

1 Answers1

7

You fell into a common newbie trap for Python. Using a list as a default variable as you did with def __init__(self, list = [0,0,0,0,0,0,0,0,0,0]) means that all instances of that class share the same list instance as the value for that argument. See also "Least Astonishment" and the Mutable Default Argument

By the way, a common idiom if you want to use a container object such as a list as a default argument, is to instead use None and check for that. For example:

def __init__(self, values=None):
    if values is None:
        values = [0] * 10

Or whatever. Not quite as clearly self-documenting as default arguments but it works.

As a side note, don't use list as a variable name, as it shadows the (somewhat commonly used) list builtin.

Community
  • 1
  • 1
Iguananaut
  • 21,810
  • 5
  • 50
  • 63
  • Well, that is a weird and unexpected answer. Was not something I was aware of at all. Thanks for the help. – Spino Prime Nov 15 '12 at 00:09
  • An approach which I prefer is to let the default argument be something immutable, such as, say, a `tuple`; and then just store the attribute as `list(values)`. This has the advantage that the user can pass, say, a generator, and the instance will still receive a list that it can index into, splice, etc. It has the quirk that passed-in lists will be copied, which "protects" the input, but might be a useless performance hit depending on what you are doing. – Karl Knechtel Nov 15 '12 at 00:42
  • I prefer this because "special cases aren't special enough" and I like to avoid conditional logic whenever there is a simple way to do so. – Karl Knechtel Nov 15 '12 at 00:43