有没有办法使字典键指向原始变量?

时间:2019-11-28 15:31:39

标签: python class dictionary pointers assign

我一直在使用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,以便通过更改字典的值来对其进行更改?

编辑:

谢谢你们!我现在知道我期望字典有不正确的行为。我将尝试另一种方法。

3 个答案:

答案 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)