Why does the contents of a tuple change when I add it to the list inside it, but it does not change when I update a variable?

myVar = ["jhhj", "hgc"] myTuple = ([1,2,3], [4,5,6], myVar) myVar.append('lololol') print myTuple 

Why and how can I change this tuple by adding after construction?

 myVar = "lol" myTuple = ([1,2,3], [4,5,6], myVar) myVar = "lolol" print myTuple 

Why will this be printed ([1,2,3], [4,5,6], "lol") instead of ([1,2,3], [4,5,6], "lolol") ?

+7
source share
6 answers

Ok, let me try to explain some images.

In Python, everything is an object. These objects refer to variables. Some kinds of objects, such as lists and tuples, simply store links to other objects.

However, when you perform

 myVar = ["jhhj", "hgc"] myTuple = ([1,2,3], [4,5,6], myVar) 

You get more or less this scenario:

A tuple pointing to three lists; a list pointing to two strings

Each object is represented by a rectangle / rectangle. We have two string objects, "jhhj" and "hgc" . In addition, we have a list object indicated by the variable myVar ; this list object points to both string objects. In addition, we have a tuple object referenced by myTuple ; this tuple object points to two other lists and the list referenced by myVar .

While doing

 myVar.append('lololol') 

what's happening? Well, the list object (which, incidentally, points to myVar ) starts to refer to another value, the string object "lololol" :

A tuple pointing to three lists; a list pointing to two strings; a new string is added to the list

Note that myVar is still referencing a list object. It so happened that the list object has changed. You can look at this list object from both myVar and the tuple, you will see the same object with the same change.

OTOH when you perform

 myVar = "lol" myTuple = ([1,2,3], [4,5,6], myVar) 

You will get something like this:

A tuple pointing to two lists and a string, also pointed by a variable

Now myVar points to the string object "lol" , and the tuple refers to its third position. Now if you follow

 myVar = "lolol" 

you just force myVar to point to another object. The tuple object still points to "lol" as before:

A tuple pointing to two lists and a string, also pointed by a variable. The variable now references another string.

So, if you assign a new value to a variable, it will simply change the value indicated by that variable. The previous value referenced by the variable will still be *, and any other variable or object pointing to it will remain pointed to it. Only the attribute variable is changed.

PS: In addition, I answered a somewhat vague question some time ago . You may find the answer helpful.

* Except for garbage collection, but this is another long story.

+7
source

All things in python are objects.

So, when you fulfill your initial assignment

myVar = "lol"

you pass myVar a reference to the lol object

Then you create a tuple. This tuple in the third slot has a link to "lol"

Then you create a new "lolol" object and give myVar a link to it. The tuple maintains the original link to "lol"

+5
source

Tuples are immutable, so you will need to build a new tuple if you want to change one of its members ...

+1
source

Tuples are immutable, but you can combine them together, for example:

 var a = (1, 2) var b = a + (3, 4) 
+1
source

In both cases, when you create a tuple, you copy the link to any myvar object at that time.

In the first case, myvar is a mutable object. You can change the object after the link to it has been stored in the tuple.

In the second case, myvar is an immutable string. You cannot change the object, but you can change what myvar refers myvar . This does not change the object that is contained in the tuple.

+1
source

Other answers have a few points that I will not repeat again, explaining the difference between names and objects. All that seems to me to be missing is an indication of when some Python code works with names and when it works with objects.

The key thing you need to understand is that the only thing that affects names directly is assignment instructions [1]. The assignment operator double-checks the name to point to another object. A name that appears in any other context is a simple position for any object that the name is associated with when this line of code is executed.

Let's look at this line from your example:

 myTuple = ([1,2,3], [4,5,6], myVar) 

myTuple appears on the left side of the assignment operator, so the name myTuple is what is affected there. myVar , on the other hand, is inside the expression, so the myVar object is tied to what is the third element of the tuple, not the name myVar .

Therefore, everything that happens later with the name myVar does not affect the tuple. But while the third element of the tuple and myVar are related to the same object, changing this object (via myVar or the tuple) will clearly affect what you get when you look at the object through any link.


[1] For extended study, def and class statements are also “assignment operators” (they create a function or class and then give it a name).

In addition, operators of type += , *= , etc. sometimes they are assignment operators, and sometimes not, depending on the type of object currently referenced by the name on the LHS:

 myList = [] myList += ['this calls a method on a list object which mutates it in place; the name is not changed'] myInt = 1 myInt += 10 # This rebinds myInt to refer to a new object 11; the object 1 is not changed 
+1
source

All Articles