What happens when you assign a value from one variable to another variable in Python?

This is my second day of learning python (I know the basics of C ++ and some OOP.), And I have a little confusion regarding variables in python.

Here is how I understand them now:

Python variables are references (or pointers?) To objects (which are mutable or immutable). When we have something like num = 5 , an immutable object 5 is created somewhere in memory, and a pair of links <object-name> of object-object-name-object is created in a specific namespace. When we have a = num , nothing is copied, but now both variables refer to the same object, and a added to the same namespace.

My book, Automating Boring Things with Python, confuses me here. Since this is a beginners book, it does not mention objects, namespaces, etc., and he tries to explain the following code:

 >>> spam = 42 >>> cheese = spam >>> spam = 100 >>> spam 100 >>> cheese 42 

The explanation that he offers is exactly the same as in the book in C ++, which I do not like, since we are dealing with references / pointers to objects. Thus, in this case, I believe that in the 3rd line, since the integers are unchanged, spam receives a completely new pointer / link to another place in memory, that is, the memory to which it originally pointed was not changed, Therefore, we have cheese , referencing the initial object that spam refers to. Is this the correct explanation?

+69
variables python object
Jul 12 '17 at 9:15 on
source share
8 answers

As a C ++ developer, you can think of Python variables as pointers.

Thus, when you write spam = 100 , it means that you are "assigning a pointer" that previously pointed to object 42 to point to object 100 .

Previously, cheese was assigned to point to the same object as the spam pointer, which at the time was 42 . Since you have not modified cheese , it still points to 42 .

In this case, immutability has nothing to do with this, since the purpose of the pointer does not change anything with respect to the object it points to.

+78
Jul 12 '17 at 9:20
source share

The way I see it, there are different views on the language.

  • "Language Advocate."
  • The prospect of a "practical programmer."
  • perspective of the "implementer".

From the point of view of a language advocate, python variables always "point to" an object. However, unlike Java and C ++, the behavior of == <=> = etc depends on the type of runtime of the objects that the variables point to. Also in python, memory is controlled by the language.

From the point of view of a practical programmer, we can consider the fact that integers, strings, tuples, etc. are immutable * objects, not direct meanings like irrelevant details. The exception is storing large arrays of numerical data, which we can use for types that can store values ​​directly (for example, numpy arrays), and not types that will contain an array full of references to tiny objects.

From the point of view of developers, most languages ​​have some kind of as-if rule, so if the indicated behaviors are correct, the implementation is correct, regardless of how things really work under the hood.

So yes, your explanation is correct from the point of view of a language attorney. Your book is correct from the point of view of a practical programmer. The actual implementation actually depends on the implementation. In integers, cpython are real objects, although small integer values ​​are taken from the cache pool and not re-created. I'm not sure what other implementations are doing (e.g. pypy and jython).

* note the difference between mutable and immutable objects here. With a mutable object, we must be careful when considering it as a value, because some other code can mutate it. With an immutable object, we have no such problems.

+20
Jul 12 '17 at 12:46 on
source share

That's right, you can use more or less variables as pointers. However, sample code would really help explain how this works.

First, we will use the id function to a large extent:

Return the "identifier" of the object. This is an integer that is guaranteed to be unique and constant for this object throughout its life. Two objects with non-overlapping lifetimes can have the same id () value.

This will probably return different absolute values ​​on your computer.

Consider the following example:

 >>> foo = 'a string' >>> id(foo) 4565302640 >>> bar = 'a different string' >>> id(bar) 4565321816 >>> bar = foo >>> id(bar) == id(foo) True >>> id(bar) 4565302640 

You can see that:

  • There are different identifiers in the original foo / bar, as they point to different objects.
  • When bar is assigned to foo, their identifiers are now the same. This is similar to the fact that they point to the same place in memory that you see when creating a pointer to C ++

when we change the value of foo, it is assigned a different id:

 >>> foo = 42 >>> id(foo) 4561661488 >>> foo = 'oh no' >>> id(foo) 4565257832 
It is also interesting to note that integers implicitly have this functionality up to 256:
 >>> a = 100 >>> b = 100 >>> c = 100 >>> id(a) == id(b) == id(c) True 

However, after 256 this is no longer the case:

 >>> a = 256 >>> b = 256 >>> id(a) == id(b) True >>> a = 257 >>> b = 257 >>> id(a) == id(b) False 

however, assigning a to b actually retain the identifier as shown above:

 >>> a = b >>> id(a) == id(b) True 
+18
Jul 12 '17 at 13:56 on
source share

Python is neither a pass by reference nor a pass by value. Python variables are not pointers, they are not references, they are not values. Python variables are names .

Think of it like “pass-by-alias” if you need the same type of phrase or maybe “pass-by-object” because you can mutate the same object from any variable that points to it, if it is changed, but reassigning the variable (alias) changes only one variable.

If that helps: C variables are fields into which you write values. Python names are tags that you add to values.

The Python variable name is the key in the global (or local) namespace, which is actually a dictionary. The base value is some object in memory. The assignment gives a name to this object. Assigning one variable to another variable means that both variables are names for the same object. Re-assigning one variable changes the object that is specified by this variable, without changing another variable. You moved the tag but did not change the previous object or any other tags on it.

In the base C code of the CPython implementation, every Python object is PyObject* , so you can think of it as working like C if you only ever had pointers to data (without pointers to pointers, there are no directly -bounded values).

you could say that Python is pass-by-value, where the values ​​are pointers ... or you could say that Python is pass by reference, where the links are copies.

+16
Jul 12 '17 at 18:52
source share

When running spam = 100 python, create another object in memory, but do not modify the existing one. so you still have cheese pointer up to 42 and spam up to 100

+9
Jul 12 '17 at 9:18
source share

What happens on the spam = 100 is the replacement of the previous value (pointer to an object of type int with value 42 ) with another pointer to another object (type int , value 100 )

+8
Jul 12 '17 at 9:17 on
source share

As @DeepSpace mentioned in the comments, Ned Batchelder does a great job of demystifying blog variables (names) and values, from which he made a presentation at PyCon 2015, Facts and Myths about Python Names and Values . It can be insightful for Pythonistas at any skill level.

+8
Jul 12 '17 at 21:47
source share

When you store spam = 42 , it creates an object in memory. Then you assign cheese = spam , it assigns the spam referenced object to cheese . And finally, when spam = 100 changes, it only changes the spam object. So cheese = 42 .

+1
Jul 12 '17 at 9:50
source share



All Articles