-2

I'm little forgotten about python sdince I don't use it since a while and I can't solve this seemingly very basic error.

I'm doing a very naif approach to code a chess engine and I'm not being able of correctly separate instances of classes.

In my code:

class Piece:
  def __init__(self, name='', symbol='', color='', value=0, position=(0,0)):
   self.name=name   
   self.color=color
...
class Army:
  def __init__(self, color="", pieces=[]):
      self.color=color
      self.pieces=pieces
black=Army()
for rank in range(8):
 black.pieces.append(Piece())
 black.pieces[rank].color="B"
 print(Army().pieces[rank].color)

Output:

B
B
B
B
B
B
B
B

Instead of '' to which Piece() defaults. Note that the output points to Army() and not to black instance for which that output would be the expected.

Shouldn't separate class instances take separate values? I really can't figure out what's going on.

My full code is:

class Game:
 def __init__(self, name="chess",score=0,board=""):
  self.name=name
  self.board=board
  self.score=score
class Board:
 def __init__(self, position="", size=[8,8]):
   self.size=size
   self.position=position
class Piece:
  def __init__(self, name='', symbol='', color='', value=0, position=(0,0)):
# vector=[[0,0],[0,0]])
   self.name=name
   self.color=color
   self.value=value
   self.position=position
#   self.vector=vector

class Army:
  def __init__(self, color="", pieces=[]):
      self.color=color
      self.pieces=pieces
chess=Game()
chess.name="FIDE"
chess.board=Board()
chess.board.size=[8,8]
checker=Piece()
checker.name="checker"
checker.value=100
checker.vector=(1,0)
black=Army()
black.color="B"
for rank in range(8):
 black.pieces.append(Piece())
 black.pieces[rank].color="B"
print(Army().pieces)

white=Army()
white.color="W"
for rank in range(8):
 white.pieces.append(Piece())
 white.pieces[rank].color="W"
 print( len(black.pieces))
for ch in white.pieces:
 print (ch.color)
print(black)
print(white)
print(len(white.pieces))
print(black.color)
#print (white.pieces.color)
  • 1
    Please supply the expected [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) (MRE). Show where the intermediate results differ from what you expected. 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. Your code snippet is not independent. Your full program is overkill. Please focus the problem, post minimal code, and include your value tracing. – Prune Feb 02 '21 at 01:06
  • 2
    Please note that "I forgot my Python skills" is a waving "red flag" that Stack Overflow is the wrong site for this problem. Please repeat [on topic](https://stackoverflow.com/help/on-topic) and [how to ask](https://stackoverflow.com/help/how-to-ask) from the [intro tour](https://stackoverflow.com/tour). Stack Overflow is not intended to replace existing documentation and tutorials. – Prune Feb 02 '21 at 01:08
  • Does this answer your question? ["Least Astonishment" and the Mutable Default Argument](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument) – Michael Butscher Feb 02 '21 at 01:10

1 Answers1

1

I suppose that's because you should not use mutable lists as a default values. All the instances of Board() keep references to the same size list. All the Army() instances use the same pieces list as well.

Please try to update your code using approach described below:

def __init__(self, color="", pieces=[]):
    self.pieces = pieces

# ->

def __init__(self, color="", pieces=None):
    if pieces is None:
        pieces = []
    self.pieces = pieces

So you'll be creating a new, separate, instance of list per each __init__() call.

More info: Mutable Default Method Arguments In Python

madbird
  • 1,326
  • 7
  • 11
  • I'll try it but I don't get it. Do you mean that if two variables have the same values they are the same and update the same? or more precisely, that if two lists are empty they update the same? weird, let me try it. – Lerian Acosenossa Feb 02 '21 at 01:18
  • I mean, when you write ```python def fn(lst=[]): ... ``` this actially means ```python _default_lst = [] def fn(lst=_default_lst): ... ``` it doesn't creates a new list when you call function, it uses already created (and bound to the other army) So you need to declare list in a function body, not in its signature. – madbird Feb 02 '21 at 01:27