-3

I am trying to program a chess computer. I am having a weird problem with a dictionary here. As you can see in the code below, I am only editing the pieces attribute of the Player object saved at 'w' in my dictionary self.players. However, when I run the code, for both Player objects created (Player('w') and Player('b')), the d[(1,1)].piece object appears in their respective Player.pieces['R']. How can this be? (In the code, only the class Board should be really important however I included the other classes so the code works).

import numpy as np

class Board:
    def __init__(self,standard=True):
            self.players={}
            self.players['w']=Player('w')
            self.players['b']=Player('b')
            d={}
            d[(1,1)]=Field(np.array([1,1]),'ds','ds'+'.png')

            d[(1,1)].piece=Rook(np.array([1,1]),'w',self)
            self.players['w'].pieces['R'].append(d[(1,1)].piece)            
                
class Player:
    def __init__(self,color,rooks=[],bishops=[],knights=[],queen=[],king=[],pawns=[]):
        self.color=color
        self.pieces={}
        self.pieces['R']=rooks

class Pieces:
    def __init__(self,position,color,board):
        self.position=position
        self.color=color
        if self.color=='w':
            self.enemycolor='b'
        else:
            self.enemycolor='w'
        self.moves=[]
        self.board=board

class Rook(Pieces):
    def __init__(self,position,color,board):
        super().__init__(position,color,board)
        self.prev_move=False
        self.typ='R'

class Field:
    def __init__(self,position,color,pic,piece=None):
        self.piece=piece
        self.position=position
        self.color=color
        self.pic=pic
b=Board()
print(b.players['w'].pieces['R'])
print(b.players['b'].pieces['R'])
joinijo
  • 353
  • 2
  • 9
  • Please supply the expected [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) (MRE). We should be able to copy and paste a contiguous block of your code, execute that file, and reproduce your problem along with tracing output for the problem points. This lets us test our suggestions against your test data and desired output. Show where the intermediate results differ from what you expected. Your posted code defines five classes and quits without doing anything. – Prune Apr 23 '21 at 20:59
  • See also [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). It's a valuable skill you're going to have to pick up sooner or later – Silvio Mayolo Apr 23 '21 at 21:00
  • Presumably this can be explained by https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – mkrieger1 Apr 23 '21 at 21:00
  • A quick glance over the code suggests that this is the [Mutable default](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument) problem. If so, this should be closed as a duplicate and deleted. – Prune Apr 23 '21 at 21:00
  • @Prune I added a few lines to produce the (un)desired output. At the others I'll have a look at what you suggested. – joinijo Apr 23 '21 at 21:04

1 Answers1

1

Your problem is on this line:

def __init__(self,color,rooks=[],bishops=[],knights=[],queen=[],king=[],pawns=[]):

The line defining the method is run only once when it is created; therefore when this method is called more than once (on the instantiation of each Player), the lists available for both objects are the same objetcs. In other words: both your players are setup with the same lists.

Create the empty lists inside the method body and it will work:

def __init__(self,color,rooks=None,bishops=None,knights=None,queen=None,king=None,pawns=None):

    self.rooks = rooks if rooks else []
    ...
jsbueno
  • 99,910
  • 10
  • 151
  • 209
  • 1
    True, now it works. I even knew about this 'problem' of python a while ago and forgot about it again. Thanks a lot! – joinijo Apr 23 '21 at 21:09