Reputation: 863
I noticed a very strange behavior when working with python that binds 2 variables, that are set equal, to the same changes and I want to know if anyone has an explanation for this behavior and if there is a better solution than mine for it.
For example, I have an array called schema1. I later need to expand schema1 with a new set of variables but I can't mess up the original array so I create schema2 by setting it equal to schema1 like so:
from someFileICreated import SomeClass
schema1 = SomeClass.SomeSchema
Suppose schema1 has array [a, b, c], then I:
schema2 = schema1
schema2.append(d, e, f)
Now, schema2 should have [a, b, c, d, e, f] However, for some reason, schema1 also has [a, b, c, d, e, f]
I don't understand this behavior, so if you have an explanation that would be great. As far as solutions go, this will work, but I'm wondering if there is another way that is better and can avoid a loop.
Instead of setting schema2 = schema1 I just do this:
schema2 = []
for x in schema1:
schema2.append(x)
Upvotes: 0
Views: 4100
Reputation: 1
When you assign an object to a variable, you are binding that name to that object. If you then set that variable to another variable, the second variable name is binding to the original object.
schema1 = SomeClass.someSchema
schema2 = schema1
In this example, schema1 and schema2 are bound to the same object. You could either use the python copy
library or if the class you are working with accepts an object of that class as parameter in the constructor you can create a new object that way. For example if you are copying a dict you can do:
from copy import copy
schema1 = { 'foo': 'bar' }
schema2 = copy(schema1)
or
schema1 = { 'foo' : 'bar' }
schema2 = dict(schema1)
The name binding is talked about in python's execution model. https://docs.python.org/3/reference/executionmodel.html
This might be a good start if you want to learn more: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
Upvotes: 0
Reputation: 100
both answer above are right but instead of doing schema1[:] you can do
from copy import copy
schema2 = copy(scheme1)
which makes it more readable and can work with other object such as dict
Upvotes: 1
Reputation: 8251
On this line:
schema2 = schema1
you are not creating a new array, but instead you are just setting the reference schema2
to point at the same array that schema1
is pointing at.
Writing
schema2 = schema1[:]
will actually create a new list by copying schema1
.
Upvotes: 1
Reputation: 399803
It's important to remember that in Python, variables are not little boxes that hold stuff, they're just handy names that are attached to stuff.
So when you do
schema1 = SomeClass.SomeSchema
schema2 = schema1
You're just attaching two names to the same piece of data, which is why the value of both variables changes.
You need to copy the actual value. For lists, one way of doing this is:
schema2 = schema1[:]
See this question for more on copying lists.
Upvotes: 2