Why are my instances changing?

I am making a class of polynomial objects represented by dictionaries:

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

This is the part of my code relevant to the question:

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)

Whenever I try to use a method __neg__, the original object changes. For instance:

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

I really can't understand why the original one is changing p1. I did not make any direct changes to it, only access to its fields.

Can anyone clarify so that I can fix this?

+4
source share
3 answers

I did not make any direct changes to it, only access to it.

Not so: look at your code ...

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()

"" , id. :

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

, .

+2

:

neg_pol = self.coeffs_dict

dict, neg_pol , (, neg_pol[key] = -self.coeffs_dict[key]) .

dicts , copy:

class Sparse_polynomial():

    # ... your other stuff

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

, :

neg_pol = self.coeffs_dict

You need a copy, so you can mutate it without ruining the original:

neg_pol = self.coeffs_dict.copy()

You might want to check out " How to assign by value in python " for a hint on how to copy other mutable objects. Python is not very consistent about how copy, for example, a type listdoes not have a method copy, and most people use notation for slicing to copy a list:

new_list = old_list[:]

As MSeifert suggested, dict recognition is a good way to generate a mutated copy:

>>> 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}
0
source

Source: https://habr.com/ru/post/1678829/


All Articles