Davoud Taghawi-Nejad
Davoud Taghawi-Nejad

Reputation: 16816

Variable referenced instead of copied

When I run the code below it removes deleted_partner from B. But as it removes it from B it also removes it from A. So that when I try to remove it from A the program crashes. What is the problem?

for deleted_partner in self.list_of_trading_partners: 
    B = A[:]
    print("t", deleted_partner)
    print(B[self.ID].list_of_trading_partners)
    B[self.ID].list_of_trading_partners.remove(deleted_partner)
    Round_neo_classic(B)
    Round_costs(B)
    if B[self.ID].final_good > reference_value:
        print("d", deleted_partner)
        print(A[self.ID].list_of_trading_partners)
        A[self.ID].list_of_trading_partners.remove(deleted_partner)

Output:

('t', 1)
[1, 2, 3, 4]
('d', 1)
[2, 3, 4]

Upvotes: 1

Views: 151

Answers (3)

Jochen Ritzel
Jochen Ritzel

Reputation: 107676

B=A[:] does copy only the list, but not it's contents. B[self.ID] and A[self.ID] still reference the same object, only A and B are different.

You might way to explicitly copy all the elements of the list too - copy.deepcopy can do this. But beware: deepcopy copies everything - it looks like you only want to copy the list_of_trading_partners, so you should probably write a __deepcopy__ method on whatever class A[self.ID] is that does just that.

Upvotes: 1

Simon
Simon

Reputation: 12488

You're not removing from B or A, but from A[some_ID].list_of_trading_partners and B[some_ID].list_of_trading_partners. [:] only makes a "shallow copy" of the list, in that it creates a new, separate list, but the elements contained in that list (one of which list_of_trading_partners is an attribute of) are not copied but referenced. Perhaps the copy module and its deepcopy function can help you?

Upvotes: 2

Htechno
Htechno

Reputation: 6127

Since you do not put the real list is hard to do tests, buy you can try with copy.copy or copy.deepcopy

import copy

for deleted_partner in self.list_of_trading_partners: 
    B = copy.copy(A)
    print("t", deleted_partner)
    print(B[self.ID].list_of_trading_partners)
    B[self.ID].list_of_trading_partners.remove(deleted_partner)
    Round_neo_classic(B)
    Round_costs(B)
    if B[self.ID].final_good > reference_value:
        print("d", deleted_partner)
        print(A[self.ID].list_of_trading_partners)
        A[self.ID].list_of_trading_partners.remove(deleted_partner)

Upvotes: 1

Related Questions