-1

I am trying to create a new variable with class Lamb (called hold) using a variable (main), which also has class Lamb. Lamb has two parameters (x and y).

I create a variable called main with class Lamb where main.x is a list. I then create hold using main.x and main.y (see code snip 2 below). When I try to change hold.x(1) it changes main.x(1) as well. This behavior is not observed when I do not use a list in main.x and hold.x.

How do I stop hold.x(1) from changing main.x(1)? A more detailed description of my problem and what I have tried is below.

I found that when I want to take a value from a variable of a certain class I cannot just assign it a new variable (hold = var.x). If I do this then when I change hold python also changes var.x as well.

To fix this I make hold have the same class as var (hold.x=var.x) as seen below

class Lamb():
def __init__(self,x,y):
    self.x = x
    self.y = y
main = Lamb([1,"a"],2)
print("main.x =",main.x,":",main)

hold = Lamb(main.x,main.y)
hold.x = "b"

print("main.x =",main.x,":",main)
print("hold.x =",hold.x,":",hold)

main.x = [1, 'a'] : <main.Lamb object at 0x01A26D10>

main.x = [1, 'a'] : <main.Lamb object at 0x01A26D10>

hold.x = b : <main.Lamb object at 0x01B606F0>

Notice that main.x != hold.x.

This works as expected, but if I try to change just the "a" value in hold.x I also change the "a" value in main.x.

class Lamb():
def __init__(self,x,y):
    self.x = x
    self.y = y

main = Lamb([1,"a"],2)
print("main.x =",main.x,":",main)

hold = Lamb(main.x,main.y)
hold.x[1] = "b"                       #[1] IS THE ONLY THING I CHANGED

print("main.x =",main.x,":",main)
print("hold.x =",hold.x,":",hold)

main.x = [1, 'a'] : <main.Lamb object at 0x01216D10>

main.x = [1, 'b'] : <main.Lamb object at 0x01216D10>

hold.x = [1, 'b'] : <main.Lamb object at 0x012606F0>

Notice now main.x = hold.x

This behavior is strange to me because of the memory calls in the print statements. main and hold both have distinct locations in memory. Maybe hold.x is pointing at main.x but that doesn't seem to be what is happening when looking at the example above.

I have a fix but I would rather not use it. I assign a value to each value in the main then use these values instead of main.x and main.y. I would rather not do this. Is there a better way to create a copy of main and change only a single value of a parameter that is a list?

x needs to have an undetermined length if I do it this way I need to have a hold value for each value in main.x.

class Lamb():
def __init__(self,x,y):
    self.x = x
    self.y = y

main = Lamb([1,"a"],2)
print("main.x =",main.x,":",main)


holdx0 = main.x[0]
holdx1 = main.x[1]
holdy = main.y

hold = Lamb([holdx0,holdx1],holdy)
hold.x[1] = "b"


print("main.x =",main.x,":",main)
print("hold.x =",hold.x,":",hold)

main.x = [1, 'a'] : <main.Lamb object at 0x01BB0710>

main.x = [1, 'a'] : <main.Lamb object at 0x01BB0710>

hold.x = [1, 'b'] : <main.Lamb object at 0x01BB0610>

Thank you for your help.

  • What this comes down to is the fact that after you do hold = Lamb(main.x,main.y), the variables main.x and hold.x both hold references to the same list. Altering the list that main.x refers to is the same thing as altering the list that hold.x refers to, because the list that main.x refers to is the list that hold.x refers to. If you don't want to see the behavior that you're seeing, consider making a copy of the list. – Tanner Swett Sep 28 '16 at 15:36
0

Once you have created main and hold, both are stored in different locations in memory, in your case: 0x01A26D10 and 0x01B606F0.

Initially, their x variables point to the same location in memory (whatever that is), where the list [1,"a"] is stored.

As soon as you assign hold.x = 'b', then hold.x points somewhere else different than main.x

But, on your second example where you assign hold.x[1] = "b", you are just changing one element of a list which is a mutable object, and therefore hold.x still points to the same place as main.x

To get the behavior you need, instead of:

hold = Lamb(main.x,main.y)

I would rather make a deep copy of main:

import copy
hold = copy.deepcopy(main)

Or, as Tanner Swett suggested, make a copy of the list:

hold = Lamb(list(main.x), main.y)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.