user3124181
user3124181

Reputation: 863

Python Changes Both Variables When Set Equal?

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

Answers (4)

GGross
GGross

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

kill129
kill129

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

Keiwan
Keiwan

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

unwind
unwind

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

Related Questions