0

Have a strange issue when using the following classes/objects. I have defined the class Document, which contains the instances of the class Items, and Items consist of instances of the class Entries.

class Document: 
  def __init__(this, items=[]):
    this.items = items
  def addItem(this, Item):
    this.items.append(Item)

class Item:
  def __init__(this, entries=[], title=""):
    this.entries = entries
    this.title = title
  def addEntry(this, Entry):
    this.entries.append(Entry)

class Entry: 
  def __init__(this, text=""):
    this.text = text   

I then run the following code, adding 'a', 'b', and 'c' as Items to the Document Doc, and then added '0', '1', and '2' as entries to each item.

list_of_letters = ['a','b','c']
list_of_numbers = ['0', '1', '2']

Doc = Document()
for letter in list_of_letters: 
  temp_item = Item(title = letter)
  for number in list_of_numbers: 
    temp_entry = Entry(text = number)
    temp_item.addEntry(temp_entry)
  Doc.addItem(temp_item)

print("begining first for loop")
for item in Doc.items:
  print(item.title)

print("begining second for loop")
for entry in Doc.items[0].entries:
  print(entry.text)

print("begining third for loop")
for entry in Doc.items[1].entries:
  print(entry.text)

As expected, the first loop prints "a", "b", "c", which was what was intended in adding Item objects to the Document. The second and third loops, however, print 0,1,2,0,1,2,0,1,2, so adding the entries to the Item object two times extra, or bascially every time an entry is added to an Item, it is added to all Items. Printout screenshot linked.

Printout

Greatly appreciate any insight on what the problem is! Could it also be something to do with Colab (what I'm using). Thanks.

  • `items=[]` is a smell, likewise `entries=[]`. Don't use mutable defaults: there's _only one instance of a list_ that's used as the default, so when you append to it, _all_ calls to the function get that now-nonempty list. – Charles Duffy Jul 27 '21 at 14:43
  • Consider `items=()`, and then `self.items = list(items)` as one alternative; or `items=None`, and `self.items = items or []` – Charles Duffy Jul 27 '21 at 14:45
  • Thanks so much, that works. Really appreciate it. Curious for my own understanding, what exactly is items=()? Is that a list? – nodeMASTER Jul 27 '21 at 15:13
  • It's an empty tuple. The key difference is that while lists are mutable, tuples are immutable, so you can't modify a tuple in-place to have a different value; any operation that "changes" a tuple actually creates a new, different one and leaves the old one the way it was. – Charles Duffy Jul 27 '21 at 15:36

0 Answers0