简体   繁体   中英

Python dict as class variable issue

I'm running into some problems while using dictionaries are Class variables in Python. I want to have a dict Class variables (a template) that gets added to every instance (users), and subsequently where every instance can change their dict values independently of each other. However, my experience is that changing a dict value in one instance also changes the dict value of the template Class variable and all other instances. This is not the case with variables of type integer, so I'm curious why dicts as class variables exhibit this behavior?

To illustrate, I assembled an example code below where I have two users who (on initialization) gets assigned "their own" dictionary. When adding values to a user, this dictionary is filled by the template dict so that the users can modify the values independently of each other. Or, at least that is what it's supposed to exemplify.

class User:
    template = {"sad": 0, "happy": 0, "meloncoli": 0}

    def __init__(self):
        self.emo = {}
    
    def new_dict(self, user_input):
        # add the template to the current instance
        self.emo = self.template
        # if the input values (strings) are in the template, then add 1 instead of 0 as value.
        for i in range(len(list(user_input.values())[0])):
            if list(user_input.values())[0][i] in self.emo:
                self.emo[list(user_input.values())[0][i]] = 1
        

user1 = User()
user_input = {
    6: ["sad", "happy"],
    }
user1.new_dict(user_input)
print(user1.emo)


user2 = User()
user_input = {
    6: ["sad"],
    }
user2.new_dict(user_input)
print(user2.emo)

The output I'm getting here is:

{'sad': 1, 'happy': 1, 'meloncoli': 0}
{'sad': 1, 'happy': 1, 'meloncoli': 0}

However, I should be getting:

{'sad': 1, 'happy': 1, 'meloncoli': 0}
{'sad': 1, 'happy': 0, 'meloncoli': 0}

This indicates that changing the dict values in the first instance changes them globally. Does anyone have any experience with this? I guess one solution is to add the template dict in the init method, but I'm not sure what is best practice in these cases.

Hope someone can enlighten me on this.

I have solved the issue below - no need to use a class variable.

class User:

    def __init__(self):
        self.emo = {"sad": 0, "happy": 0, "meloncoli": 0}

    def new_dict(self, user_input):
        # if the input values (strings) are in the template, then add 1 instead of 0 as value.
        for i in range(len(list(user_input.values())[0])):
            if list(user_input.values())[0][i] in self.emo:
                self.emo[list(user_input.values())[0][i]] = 1

Running the below:

user1 = User()
user_input = {
    6: ["sad", "happy"],
    }
user1.new_dict(user_input)
print(user1.emo)


user2 = User()
user_input = {
    6: ["sad"],
    }
user2.new_dict(user_input)
print(user2.emo)

This will yield:

{'sad': 1, 'happy': 1, 'meloncoli': 0}
{'sad': 1, 'happy': 0, 'meloncoli': 0}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM