Python Forum

Full Version: Instances in classes
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
When I create 2 instances of a class and modify one, the other also gets modified. What am I doing wrong?

class superGrid:
    
    def __init__(self, square, size = 10):
        self.square =  square
        self.size = size
        
    def shuffle(self):
        self.square[3][7] = '#'
        
    def printGridSquare(self):
        print self.square[3][7]
    
class gridSquare(superGrid):
    new = 10*[10*['0']]
    
    size1 = len(new)
    def __init__(self, size = size1, square = new):
        self.square =  square
        self.size = size
        
# Create an instance of the grid square:
g = gridSquare()
s = gridSquare()
g.printGridSquare()
s.printGridSquare()
g.shuffle()
g.printGridSquare()
s.printGridSquare()
Beginners mistake - both classes get copy of the same class variable SuperGrid.new, instead of new lists created per class.
Even worth - 10 * [10 * [0]]  - in Python, you usually put list on the left! - creates list of 10 references to innermost list

def __init__(self, square_size):
    self.square = [[0] * square_size for _ in range (square_size)]
will produce 10 individual lists of 10 individual sub-lists for each class - given that square_size is 10
Many thanks for that - I don't think I would ever have found it without help.

It doesn't immediately solve my problem, as the new square is actually filled with 100 different initial values - the example I gave was the shortest code that exhibited the problem. At least I know where to look now.
(Apr-20-2017, 03:01 PM)dannyH Wrote: [ -> ]Many thanks for that - I don't think I would ever have found it without help.

It doesn't immediately solve my problem, as the new square is actually filled with 100 different initial values - the example I gave was the shortest code that exhibited the problem.  At least I know where to look now.

Your are welcome. 
And you may use copy.deepcopy - if you want to use list of some fixed initial values for you square
Many thanks for that again. My actual code (not working yet) is:
class gridSquare(superGrid):

    new =    [['0',' ','F','O','W','E','K','T','A','H'],\
              ['1','A','G','O','X','E','L','U','B','I'],\
              ['2','A','H','P','Y','E','M','U','C','I'],\
              ['3','B','I','Q','Z','E','N','V','D','J'],\
              ['4','C','I','R',' ','F','O','W','E','K'],\
              ['5','D','J','S','A','G','O','X','E','L'],\
              ['6','E','K','T','A','H','P','Y','E','M'],\
              ['7','E','L','U','B','I','Q','Z','E','N'],\
              ['8','E','M','U','C','I','R',' ','F','O'],\
              ['9','E','N','V','D','J','S','A','G','O']]
    
    size1 = len(new)

    def __init__(self, size = size1, square = new):
        self.square =  square
        self.size = size
1) You don't need backslashes between lines.
2) Instead of class-level init-variables, why not have all that in __init__, and have the default value be None and use the default values if nothing is passed?  That way you never have to deal with shared references, since the variables simply never exist outside of an instance.

Something like:
class gridSquare(object):
   def __init__(self, size = None, square = None):
       if square is None:
           square = [
                ['0',' ','F','O','W','E','K','T','A','H'],
                ['1','A','G','O','X','E','L','U','B','I'],
                ['2','A','H','P','Y','E','M','U','C','I'],
                ['3','B','I','Q','Z','E','N','V','D','J'],
                ['4','C','I','R',' ','F','O','W','E','K'],
                ['5','D','J','S','A','G','O','X','E','L'],
                ['6','E','K','T','A','H','P','Y','E','M'],
                ['7','E','L','U','B','I','Q','Z','E','N'],
                ['8','E','M','U','C','I','R',' ','F','O'],
                ['9','E','N','V','D','J','S','A','G','O']
           ]
       if size is None:
           size = len(square)
       self.square =  square
       self.size = size

grid = gridSquare()
print(grid.size) # 10
print(grid.square) # ...the grid
Thanks. That looks like a safer solution.