我一直在使用Python中的类属性和字典遇到问题。我有以下课程:
class Test:
def __init__(self, a):
self.a = a
self.dictionary = {'key': self.a}
def check(self, string):
print("Before: ",self.a)
self.dictionary[string] += 2
print("After (Dictionary): ",self.dictionary[string])
print("After (Original variable): ",self.a)
然后我从中创建一个对象测试:
test = Test(5)
问题是:当我使用检查方法时:
test.check('key')
输出为:
Before: 5
After (Dictionary): 7
After (Original variable): 5
我期望能够通过更改字典中的self.a
值(在其中我分配了self.dictionary
属性)来更改类中的属性self.a
。但是发生的事情是原始属性self.a
并没有改变,而字典中原本应该为self.a
的值却发生了变化。
有人可以向我解释为什么会这样吗?我假设字典正在创建self.a
的副本作为'key'
的值。有什么办法可以使字典的值指向原始变量self.a
,以便通过更改字典的值来对其进行更改?
编辑:
谢谢你们!我现在知道我期望字典有不正确的行为。我将尝试另一种方法。
答案 0 :(得分:1)
这与类属性的属性无关,而与字典在Python中的工作方式以及整数不可变的事实有关。为了说明这一点,当您这样做时会发生同样的情况:
value = 5
dictionary = {"key": value}
dictionary["key"] += 2
print(value)
# > 5
print(dictionary["key"])
# > 7
请务必注意,这是行不通的,因为
self.a
是整数,在Python中是不可变类型。这意味着您不会通过执行类似self.dictionary[string] += 2
的操作来更改整数的值。
现在,对于您的问题而言,最有效的方法如下:在其中声明一个列表而不是一个整数,以保留 mutability 属性:
class Test:
def __init__(self, a):
self.a = [a] # instead of self.a = a
self.dictionary = {'key': self.a}
def check(self, string):
print("Before: ",self.a[0])
self.dictionary[string][0] += 2
print("After (Dictionary): ",self.dictionary[string][0])
print("After (Original variable): ",self.a[0])
test = Test(5)
# > Before: 5
# > After (Dictionary): 7
# > After (Original variable): 7
答案 1 :(得分:1)
self.a
指向int
对象,并且int是不可变的。即它们不能更改。创建字典对象时,您要说的是将此键指向self.a指向的同一位置。由于int
是不可变的,因此当您更改字典键指向的值时,会在新的存储位置创建一个新的对象,因此现在dict键指向该新的存储位置,而不是与self.a
仍指向。
因此,您现在拥有self.a指向拥有int 5的存储位置,而dict键指向拥有int 7的另一个存储位置。
更新
根据您的评论进行更新,使self.a和dict键值始终指向同一项的唯一方法是使用可变数据类型(例如list)。由于列表是可变的,因此当您更改列表中的值时,self.a和dict仍指向同一列表,并且仅更改了列表中的值。但是,所有对int值的引用都需要通过列表中的第一个元素进行访问
class Test:
def __init__(self, a):
self.a = [a]
self.dictionary = {'key': self.a}
def check(self, string):
print("Before: ", self.a[0])
self.dictionary[string][0] += 2
print("After (Dictionary): ", self.dictionary[string][0])
print("After (Original variable): ", self.a[0])
test = Test(5)
test.check('key')
输出
Before: 5
After (Dictionary): 7
After (Original variable): 7
但是正如我在评论中所说。由于什么原因,您需要在类实例中具有两个不同的属性/对同一值的引用。机会就是您想要实现的目标,比这种方法有更好的方法
答案 2 :(得分:0)
根据您的代码,Test类的2个实例变量为: self.a = a self.dictionary = {'key':self.a}
在检查方法中,您正在更改/更新self.dictionary变量,而不是在self.a上 (self.dictionary [string] + = 2) 如果要更新self.a,则self.dictionary和self.a是两个不同的变量,而不可以执行以下操作:
class Test:
def __init__(self, a):
self.a = a
self.dictionary = {'key': self.a}
def check(self, string):
print("Before: ",self.a)
self.a+=2
self.dictionary[string] = self.a
print("After (Dictionary): ",self.dictionary[string])
print("After (Original variable): ",self.a)
输出将是:
('Before: ', 5)
('After (Dictionary): ', 7)
('After (Original variable): ', 7)