0

I am trying to fill a dict of objects with each having a list of strings, all from a given list of strings. The problem is that when I want to replace a single element of the dict, every element changes.

Person class:

class Person:

    messages = []

    def __init__(self, p):
        self.name = p

    def add_message(self, m_text):
        self.messages.append(m_text)

Main code:

chat_messages_list = ["Eva: Eva's first text", "Eva: Eva's second text", "Eva: Eva's third text",
                      "Harry: Harry's first text", "Harry: Harry's second text", "Harry: Harry's third text",
                      "Ellis: Ellis' first text", "Ellis: Ellis' second text", "Ellis: Ellis' third text"]
dict_persons = {}

for element in chat_messages_list:

    split_messages = element.split(": ")
    name = split_messages[0]
    message_text = split_messages[1]

    # Create Person in list if not already exists
    if name not in dict_persons:
        dict_persons[name] = Person(name)

    person = dict_persons[name]

    # THE PROBLEM: Following line will add message_text to EVERY Person in dict_persons
    person.add_message(message_text)

for key, value in dict_persons.items():
    print("{0}: {1}".format(key, value.messages))

Expected result:

Eva: ["Eva's first text", "Eva's second text", "Eva's third text"]
Harry: ["Harry's first text", "Harry's second text", "Harry's third text"]
Ellis: ["Ellis' first text", "Ellis' second text", "Ellis' third text"]

Actual result:

Eva: ["Eva's first text", "Eva's second text", "Eva's third text", "Harry's first text", "Harry's second text", "Harry's third text", "Ellis' first text", "Ellis' second text", "Ellis' third text"]
Ellis: ["Eva's first text", "Eva's second text", "Eva's third text", "Harry's first text", "Harry's second text", "Harry's third text", "Ellis' first text", "Ellis' second text", "Ellis' third text"]
Harry: ["Eva's first text", "Eva's second text", "Eva's third text", "Harry's first text", "Harry's second text", "Harry's third text", "Ellis' first text", "Ellis' second text", "Ellis' third text"]

Wy are the strings being added to ALL the objects in the dict, instead of just the desired one?

sjorsng
  • 13
  • 3
  • 3
    Yes, of course, because you are *appending to the same list*, that is, you are appending to the list you defined in your class as `messages = []`, which is a *class level attribute* shared by *all instances*. – juanpa.arrivillaga Jun 14 '17 at 21:37

2 Answers2

3

Initialize messages field inside the __init__ of Person, i.e. self.messages = [] to make it an instance field.
Right now it's a class-level field, so all instances share the same list.

Lemx
  • 166
  • 2
  • 6
1

Try putting messages = [] in your init:

class Person:

    def __init__(self, p):
        self.name = p
        self.messages = []

    def add_message(self, m_text):
        self.messages.append(m_text)

This worked for me!

PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
cosinepenguin
  • 1,545
  • 1
  • 12
  • 21