Python 类的字典的值在分配给不同的变量时会发生变化



我是Python的新手,我有一个类,比如:

class UserInfo():
def __init__(self):
self.level = 1
self.type = 'A'
self.info = {
'name ' : 'John',
'age ' : 20,
'gender  ' : 'Male',
'job' : 'student',
}
def getInfo(self):
return self.info

等等。。。。。

然后我创建了一个类的实例:

ui = UserInfo()
# display original class info
print(ui.getInfo())
# {
#    'name ' : 'John',
#    'age ' : 20,
#    'gender  ' : 'Male',
#    'job' : 'student',
# }
myinfo = ui.getInfo()
# change "myinfo"
myinfo.update({
'name ' : 'May',
'age ' : 18,
'gender  ' : 'Female',
'job' : 'lecturer',
})

但当我再次尝试显示原始类信息时,我得到了:

print(ui.getInfo())
# {
#   'name ' : 'May',
#   'age ' : 18,
#   'gender  ' : 'Female',
#   'job' : 'lecturer',
# }

我所期望的是

print(myinfo)
# {
#   'name ' : 'May',
#   'age ' : 18,
#   'gender  ' : 'Female',
#   'job' : 'lecturer',
# }
print(ui.getInfo())
# {
#    'name ' : 'John',
#    'age ' : 20,
#    'gender  ' : 'Male',
#    'job' : 'student',
# }

为什么我更新了myinfo,但它也更改了类的值?如何避免这种情况?我只想修改myinfo


编辑1:

感谢大家回答我的问题。我刚试过使用return self.info.copy()当我尝试做myinfo.update时,它工作得很好

但现在我有另一个问题,当我的dict包含另一个dict时,如果我试图在里面编辑dict,它就不能再工作了:

class UserInfo():
def __init__(self):
self.level = 1
self.type = 'A'
self.info = {
'name ' : 'John',
'age ' : 20,
'gender  ' : 'Male',
'job' : 'student',
'favorite' : {
'food' : 'pizza',
'sport' : 'badminton',
'game' : 'none',
},
}
def getInfo(self):
return self.info.copy()
ui = UserInfo()
print(ui.getInfo())
# {
#   'name ': 'John',
#   'age ': 20,
#   'gender  ': 'Male',
#   'job': 'student',
#   'favorite': {
#       'food': 'pizza',
#       'sport': 'badminton',
#       'game': 'none'
#   }
#}
myinfo = ui.getInfo()
myinfo['favorite'].update({'game' : 'mobile'})
print(ui.getInfo())
#   {
#     'name ': 'John',
#     'age ': 20,
#     'gender  ': 'Male',
#     'job': 'student',
#     'favorite': {
#       'food': 'pizza',
#       'sport': 'badminton',
#       'game': 'mobile'
#     }
#   }

您收到的是同一个类,因为您正在更改最初放入的值。我建议将字典作为属性传递到类中,如下所示:

class UserInfo():
def __init__(self, dict_info):
self.level = 1
self.type = 'A'
self.info = dict_info
def getInfo(self):
return self.info
# pass the dictionary through the class instance
dict_info = {
'name ' : 'John',
'age ' : 20,
'gender  ' : 'Male',
'job' : 'student',
}   
ui = UserInfo(dict_info)
# display original class info
print(dict_info)
# Display changed class info
myinfo = ui.getInfo()
# change "myinfo"
myinfo.update({
'name ' : 'May',
'age ' : 18,
'gender  ' : 'Female',
'job' : 'lecturer',
})
ui.getInfo()

如果你在方法中返回值,我也不会打印它(就像你在print(ui.getInfo)中所做的那样。你也可以只创建一个新的字典(复制(。

您的变量myinfo被分配给ui实例的self.info。所以当你修改myinfo时,你也在修改ui的self.info

我真的不确定你想用我的信息做什么。如果你想要两个不同的UserInfo,你需要创建另一个实例,比如这个

ui = UserInfo()
ui2 = UserInfo()
myinfo = ui2.getInfo()
myinfo.update({
'name ' : 'May',
'age ' : 18,
'gender  ' : 'Female',
'job' : 'lecturer',
})
print(ui.getInfo())
print(myinfo)

输出

{'name ': 'John', 'age ': 20, 'gender  ': 'Male', 'job': 'student'}
{'name ': 'May', 'age ': 18, 'gender  ': 'Female', 'job': 'lecturer'}

如果你只想拥有不同的信息,那么你需要使用返回信息的副本。

防止这种情况发生的一种方法是让getInfo返回信息的副本,而不是信息本身,另一种方法(正如Green05的回答所说(是复制getInfo的结果。

第一个解决方案:

class UserInfo():
def __init__(self):
self.level = 1
self.type = 'A'
self.info = {
'name ' : 'John',
'age ' : 20,
'gender  ' : 'Male',
'job' : 'student',
}
def getInfo(self):
return self.info.copy()

第二种解决方案:myInfo = ui.getInfo().copy()

之所以会发生这种情况,是因为Python允许从外部更改类中的属性,而不管它们是否被别名为其他属性。ui.info是myInfo的别名,所以更改myInfo实际上只是更改ui.info。

实际情况是,当您返回self.info时,您并没有返回self.info中dictionary的,而是返回名称self.info所指向的dictionary对象本身。更改新变量也会更改类对象中的信息,因为该变量现在只是self.info的另一个名称。您可以通过返回字典的副本来解决此问题,这将创建一个与原始字典分离的新字典对象。这可以通过copy()方法来完成,该方法返回字典的新副本,如下所示:

class UserInfo():
def __init__(self):
self.level = 1
self.type = 'A'
self.info = {
'name ' : 'John',
'age ' : 20,
'gender  ' : 'Male',
'job' : 'student',
}
def getInfo(self):
return self.info.copy()

复制返回的字典怎么样?

myInfo = ui.getInfo()

编辑

要回答您的后续问题,

当您使用copy时,它会返回一个具有相同对象的不同字典。这意味着,如果您更改字典B的元素A,它是一个可变对象,就像字典一样,那么字典A在B和B的副本中都会更改。

为了避免这种情况,您需要一个同时复制所有元素的副本。python中有一种方法:deepcopy((。

因此,为了获得所需的结果,请执行以下操作:

myInfo = ui.getInfo().deepcopy()

Python字典是可变的。可变对象在Python中通过引用传递,因此当更新引用时,更改会反映在原始对象中。您可以通过创建对象的副本来解决此问题。

import copy
ui = UserInfo()
myinfo = copy.copy(ui.getInfo())
myinfo.update({
'name ' : 'May',
'age ' : 18,
'gender  ' : 'Female',
'job' : 'lecturer',
})
print(myinfo)
# {
#   'name ' : 'May',
#   'age ' : 18,
#   'gender  ' : 'Female',
#   'job' : 'lecturer',
# }
print(ui.getInfo())
# {
#    'name ' : 'John',
#    'age ' : 20,
#    'gender  ' : 'Male',
#    'job' : 'student',
# }

最新更新