我的实例为什么会改变?

4

我正在创建一个多项式对象的类,由字典表示:

3*x^2+x+2 == {2:3, 1:1, 0:2}

这是与问题相关的代码部分:

class Sparse_polynomial():
    def __init__(self, coeffs_dict):
        self.coeffs_dict = coeffs_dict


    def __repr__(self):
        terms = [" + ("+str(self.coeffs_dict[k])+"*x^" + str(k)+")" \
                 for k in sorted(self.coeffs_dict.keys(), reverse=True)]
        terms = "".join(terms)
        return terms[3:]  

    def __neg__(self):
        neg_pol= self.coeffs_dict
        for key in self.coeffs_dict:
            neg_pol[key]= -self.coeffs_dict[key]
        return Sparse_polynomial(neg_pol)

每当我尝试使用__neg__方法时,原始对象都会发生变化。例如:

>>> p1= Sparse_polynomial({1:3,5:1})
>>> p1
(1*x^5) + (3*x^1)
>>> -p1
(-1*x^5) + (-3*x^1)
>>> p1
(-1*x^5) + (-3*x^1)
>>> 

我真的不明白为什么原始的p1会改变。我没有直接对它进行更改,只是访问了它的字段。

有人能澄清一下,这样我就可以修复它了吗?


new_dict = dict(old_dict) 会为你复制它,你需要的是一个副本而不是引用。 - syntaxError
3个回答

2

我没有直接对它进行更改,只是访问了它的字段。

这并不正确:看看你的代码...

def __neg__(self):
    neg_pol= self.coeffs_dict
    for key in self.coeffs_dict:
        neg_pol[key]= -self.coeffs_dict[key]

你获取了系数字典的引用并否定了每个成员。这不是副本;它是对原始字典的引用。

如果你想返回一个单独的字典,那么可以使用几种可用的复制方法之一。其中一个流行的方法是使用类自身的copy方法:

neg_pol = self.coeffs_dict.copy()

要检查项目的“handle”,请使用id方法。例如:

print id(self.coeffs_dict), id(neg_pol)

这很明显表明这两个变量名指向同一个对象。

1
正如其他人指出的那样:

neg_pol = self.coeffs_dict

如果不创建新的字典,neg_pol 只是对于同一个字典的另一个引用,任何更改(例如 neg_pol[key] = -self.coeffs_dict[key])将对两个变量都可见。
个人而言,我更喜欢使用 dict-comprehensions 创建新字典,而不仅仅使用 copy
class Sparse_polynomial():

    # ... your other stuff

    def __neg__(self):
        return Sparse_polynomial({key: -value for key, value in self.coeffs_dict.items()})

0

这不是复制品,只是对原始词典的引用:

neg_pol = self.coeffs_dict

你希望得到一份副本,这样你就可以对其进行修改,而不会影响原始版本:
neg_pol = self.coeffs_dict.copy()

你可能想查看 "如何在Python中按值赋值",以获取有关如何复制其他可变对象的线索 - Python 在复制内置对象方面并不一致,例如 list 类型没有 copy 方法,大多数人使用切片符号来复制列表:
new_list = old_list[:]

如MSeifert所建议的那样,字典推导式是生成突变副本的好方法:
>>> original_dict = {'a': 2, 'b': 3}
>>> square_dict = {k + "²": v * 2 for k, v in original_dict.items()} 
>>> double_dict
{'a²': 4, 'b²': 9}
>>> original_dict
{'a': 1, 'b': 2}

一个好问题就是成功的一半,所以非常欢迎您提问! - Paulo Scardine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接