1

I created a node class like this:

  def __init__(self, data, incoming = [], outgoing = []):
    self.data = data
    self.incoming = incoming
    self.outgoing = outgoing

  def addIncoming(self, incoming):
    self.incoming.append(incoming)

  def addOutgoing(self, outgoing):
    self.outgoing.append(outgoing)

where every instance was initialized like Node(number) so the incoming and outgoing parameters were defaulted to an empty list. I also had functions that appended other nodes to the incoming and outgoing list but when I did that, it was appending to every instance. For example lets say I had a=Node(1) and b=Node(2). If I did a.addIncoming(b) and printed a.incoming and b.incoming, they both would print Node b. Why are these values shared between separate instances?

When I updated my init function to be

  def __init__(self, data, incoming = [], outgoing = []):
    self.data = data
    self.incoming = []
    self.outgoing = []

everything worked as expected but I feel like the two should work the same. What am I misunderstanding here?

Notorious776
  • 453
  • 6
  • 19
  • 2
    This has nothing to do with a class. Default parameter values are only evaluated once. This means that `[]` there creates only one list object for all function calls and object instances. – Michael Butscher Jul 27 '20 at 16:54
  • There are enough differences between this question and the linked duplicate that I thought it deserved to remain open. – Mark Ransom Jul 27 '20 at 16:58
  • Dang, I keep forgetting the dupe-hammer works in both directions. – Mark Ransom Jul 27 '20 at 16:59
  • Read [Default Parameter Values in Python](http://effbot.org/zone/default-values.htm). – Mark Tolonen Jul 27 '20 at 17:10
  • 1
    @MarkRansom what "differences"? It's exactly the same problem, and has been covered in great detail on the canonical post. – jonrsharpe Jul 27 '20 at 17:10
  • @jonrsharpe half the problem in that post is caused by returning a list from the function. This question involves `__init__` from which nothing gets returned. – Mark Ransom Jul 27 '20 at 17:12
  • @MarkRansom that's just the way in which you see the problem manifest, the binding behaviour is identical. Also there *are* class-based examples in the dupe's answers. Your answer doesn't touch on any such distinction at all. – jonrsharpe Jul 27 '20 at 17:13
  • @jonrsharpe To me the questions are clearly different, even if the same explanation suffices for both. I've never thought that a dupe should be defined by duplicate answers rather than duplicate questions. – Mark Ransom Jul 27 '20 at 17:17
  • @MarkRansom that's *exactly* what defines a dupe, we're trying to get people to the content that answers their question. Your claim that the OP needs a specific solution to their unique problem would ring a lot truer if you'd bothered to provide one. – jonrsharpe Jul 27 '20 at 17:26
  • @jonrsharpe compare the answer I left on that other question to the answer I left here, and tell me how similar they are. That answer would be completely out of place here. – Mark Ransom Jul 27 '20 at 19:10

1 Answers1

2

Default parameters are evaluated when the function is defined, and stored with the function. So __init__ gets those empty lists, but every time you modify them the modifications are saved.

Remember that in Python, making new assignments with = does not make a copy of the data. Those lists are shared with every assignment you make.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622