Python, memory variables in memory

a=[1234,1234] #list a [1234, 1234] id(a[0]) 38032480 id(a[1]) 38032480 b=1234 #b is a variable of integer type id(b) 38032384 

Why id (b) is not the same as id (a [0]) and id (a [1]) in python?

+5
source share
4 answers

When the CPython REPL executes the string, it will:

  • parse and compile it to the bytecode code object, and then
  • execute bytecode.

The compilation result can be checked using dis module :

 >>> dis.dis('a = [1234, 1234, 5678, 90123, 5678, 4321]') 1 0 LOAD_CONST 0 (1234) 2 LOAD_CONST 0 (1234) 4 LOAD_CONST 1 (5678) 6 LOAD_CONST 2 (90123) 8 LOAD_CONST 1 (5678) 10 LOAD_CONST 3 (4321) 12 BUILD_LIST 6 14 STORE_NAME 0 (a) 16 LOAD_CONST 4 (None) 18 RETURN_VALUE 

Note that all 1234s are loaded with " LOAD_CONST 0 ", and all 5678s are loaded with " LOAD_CONST 1 ". They relate to the constant table associated with the code object. Here's the table (1234, 5678, 90123, 4321, None) .

The compiler knows that all 1234 copies in the code object are the same , so it will only select one object for all of them.

Therefore, as OP observed, a[0] and a[1] really refer to the same object: the same constant from the table of constants of the code object of this line of code.

When you execute b = 1234 , it will be compiled and executed again, independent of the previous line, so another object will be selected.

(You can read http://akaptur.com/blog/categories/python-internals/ for a brief introduction on interpreting code objects)


Outside of the REPL, when you execute the *.py file, each function compiles into separate code objects, so when you run it:

 a = [1234, 1234] b = 1234 print(id(a[0]), id(a[1])) print(id(b)) a = (lambda: [1234, 1234])() b = (lambda: 1234)() print(id(a[0]), id(a[1])) print(id(b)) 

We can see something like:

 4415536880 4415536880 4415536880 4415536912 4415536912 4415537104 
  • The first three numbers have the same address 4415536880 and belong to the constants of the code object "__main__"
  • Then a[0] and a[1] have the addresses 4415536912 of the first lambda.
  • b has the address 4415537104 second lambda.

Also note that this result is valid only for CPython. Other implementations have different constant extraction strategies. For example, running the above code in PyPy gives:

 19745 19745 19745 19745 19745 19745 
+2
source

There is no rule or guarantee that id (a [0]) should be equal to id (a [1]), so the question itself is controversial. The question you should ask is that id(a[0]) and id(a[1]) are actually the same.
If you execute a.append(1234) and then id(a[2]) , you may or may not get the same identifier. As @hiro protagonist pointed out, these are just internal optimizations you should not depend on.

+1
source

The Python list is very different from array C.

Array C is just an adjacent memory block, so the address of its first (0th) element is the address of the array itself, by definition. Accessing an array in C is just pointer arithmetic, and the notation [] is just a thin crust of syntactic sugar over that pointer arithmetic. The expression int x[] is just another form of int * x .

For example, suppose that in in Python, id(x) is the β€œmemory address of X” because *x will be in C. (This is not true for all Python implementations, not even guaranteed in CPython. This is just a unique number.)

In C, int is just an architecture-dependent number of bytes, so for int x = 1 expression *x points to these bytes. Everything in Python is an object, including numbers. This is why id(1) refers to an object of type int describing number 1 . You can call its methods: (1).__str__() will return the string '1' .

So, when you have x = [1, 2, 3] , id(x) is a "pointer" to a list object with three elements. The list object itself is quite complex. But x[0] is not bytes that contain an integer value of 1; it internally refers to an int object for the number 1. Thus, id(x[0]) is a "pointer" to this object.

In terms of C, the elements of an array can be considered as pointers to the objects stored in it, and not the objects themselves.

Since it makes no sense to have two objects representing the same number 1, id(1) will always be the same when running the Python interpreter. Illustration:

 x = [1, 2, 3] y = [1, 100, 1000] assert id(x) != id(y) # obviously assert id(x[0]) == id(y[0]) == id(1) # yes, the same int object 

CPython actually predefines objects for some of the most used small numbers ( see comments here ). For large numbers, this is not the case, which can lead to two "copies" of a larger number having different id() values .

+1
source

You should notice that: id () actually gives id the values ​​of variables or literals. For each literal / value that is used in your program (even in the ID () itself), id () returns (tries to return) a unique identifier for the literal / variable in the program life cycle. This can be used:

  • User: to check if two objects / variables coincide: a - b
  • Python: optimize memory, i.e. avoid unwanted duplication of the same material in memory.

For your case, it is not even guaranteed that [0] and [1] will give the same identifier, although the value of both may be the same. It depends on the order / chronology of creating literals / variables in the life cycle of the python program and the internal processing of python.

Case 1:

 Type "help", "copyright", "credits" or "license" for more information. >>> a=[1234,1234] >>> id(a[0]) 52687424 >>> id(a[1]) 52687424 

Case 2 (note that at the end of the case, the values ​​[0] and [1] have the same value, but different identifiers):

 Type "help", "copyright", "credits" or "license" for more information. >>> a=[1,1234] >>> id(1) 1776174736 >>> id(1234) 14611088 >>> id(a[0]) 1776174736 >>> id(a[1]) 14611008 >>> a[0]=1234 >>> id(1234) 14611104 >>> id(a[0]) 14611152 >>> id(a[1]) 14611008 >>> 
+1
source

Source: https://habr.com/ru/post/1266497/


All Articles