vary basic pyton variable problem

if my code looks like this:

a = b

then from now on if I change “b”, I will also change “a”. I just want to change “a” to be “set” to b that one time. I don’t want them to be linked.

I know the answer to this question is out there. I just don’t know how to google the question. forgive me.

[SOLVED]

the variables I was using contained lists. I needed to use a “splice notation” [:]

a = b[:]

Hehe, this question is not basic at all, this is very deep! Coming from a C++ background, I asked myself the same when I learned Python, and it took me a long time to figure it out.

In Python, you never assign the value of anything, ever. You just create references.
If you do:


a = "Hello"
b = a

then Python creates a new string object “Hello”. It really is an object, you can do “Hello”.upper() for example.
But you can never change it, Python doesn’t allow you to. Python variables like a and b are simply references to the “Hello” object.

An operation like “a = b” is in principle much faster in Python than in C++, because no copy of “Hello” is ever made (the variables just point to the same object).

The C/C++ equivalent would be more or less this:


PyObject *a;
PyObject *b;
string hello_object("Hello");
a = (PyObject *)  &hello_object;
b = a;

So, there is no “linkage” in Python, and changing (re-assigning) a will not change b.

It is of course different if a and b are containers (lists and dicts). You cannot assign to the containers, but you can modify their contents (the references to other Python objects they contain). So, for example:


a = [1,2,3]
b = a
a.append(4)

will have a and b point to the same list [1,2,3,4].

On the other hand,


a = [1,2,3]
b = a
a = [1,2,3,4]

will have a and b point to two different list objects.

this is the idea of link var like
a=b
a will reference back to b var!

here is another example for list

Difference in in the way the list is referenced too

data2.append(list(dataorig2[0])) # unlink only pass the data
data1.append(dataorig1[0]) # link list

this is how it works in python!

happy bl

An easy way to do it:

for strings/lists:
a = b[:] #This creates a new variable a with the contents of b

for ints/floats/etc:
a = b+0 #This creates a new variable a with the value of b

this is the idea of link var like
a=b
a will reference back to b var!

it’s called alias

Thats it! the “[:]” (splice notation). I should have mentioned that I was using lists. thank you all for the help, especially sjoerd for such an in-depth answer.

it’s not limited to lists, it also works on tuples (but not useful here for copying, rather for unpacking) and any class derived from these. It does not for dicts, but you can use your_dict.copy() instead. Copy() works on lists as well, not sure what “shallow” means in the docs though: “L.copy() -> list – a shallow copy of L”

i think copy work only on one level for list which i guess is shallow copy
for multi level call deep copy there is arother command!

happy bl

Reference and test script:

http://docs.python.org/3.3/library/copy.html

l = [1,2,3,[4,5]]
m = l.copy() # shallow copy

# A sublist in the list l
print(l[3])
#~ [4, 5]

# Set first element to 0
l[0] = 0
print(l)
#~ [0, 2, 3, [-1, 5]]

# Above change to l did not affect m
print(m)
#~ [1, 2, 3, [-1, 5]]

# Set new value to element in sublist in l:
l[3][0] = -1
print(l)
#~ [1, 2, 3, [-1, 5]]

# Sine it's a shallow copy, the sublist changed too (it was not deep-copied)
print(m)
#~ [1, 2, 3, [-1, 5]]


There’s no deepcopy() for lists btw.

i found this example


 
print ('Deep copy module :')
print ()
 
from copy import deepcopy
 
listB=[]
listA=[ [ [[10,15],1,2],[3,4,5] ] , [ [6,7,8],[9,10,11] ] ]
print ('listA =',listA,'
')
print ('listB =',listB,'
')
print ()
print ('listB = deepcopy(listA)')
listB = deepcopy(listA)
print ()
print ('listA =',listA,'
')
print ('listB =',listB,'
')
print ()
print ('listA[0][0][0][0] = 1')
listA[0][0][0][0] = 1
print ('listA =',listA,'
')
 
 
 
print ()
print ('&&&&&&&')
print ()
 


byt there are other examples too

salut

You are correct about lists, but the +0 for ints/floats is unnecessary.

copy.deepcopy(x) just works also if x is a list, afaik

it does indeed, i just expected deepcopy on the list itself, not a module function

have to find my original doc for this
why it is needed
i think i has something to do with multi level lists!

thanks

I agree, that’s a bit of a missing feature in Python, they should do something like this:


class objekt(object):
  def __deepcopy__(self):
    import copy
    return copy.deepcopy(self)
  def deepcopy(self):
    return self.__deepcopy__()

and have all classes inherit from objekt.

Yes, use deepcopy() if your list contains other containers: lists, dicts or class instances (in Python, class instances are dicts with syntactic sugar, unlike C++/Java, where they are C structs with syntactic sugar).

there is also another way to do it without using the new module!

lists are very powerfull but can also be a nghtmare!

thanks