pythonlistcpythonindirection

Memory address of list elements in cpython


I have heard that Python uses indirection to implement lists. That is, each element in a Python list is actually a pointer or reference to the place in memory where the actual element data (which could be an integer, string or any other data type) is stored. So when I created a list using

a = ["xyz", 2, "deer"]
id(a[0])

I get 43449600. However when I do this:

id(a[1])
id(a[2])

yields 1403048416 and 43489824 respectively, instead of the expected 43449616 (or some multiple), and 43449632 (or some multiple) assuming memory pointers use the same chunk of memory!

What is wrong with my understanding of indirection (or with calling id())?


Solution

  • When you use id() you are pulling the object out of the array and getting the address of the object. You can see in the following example that the string "xyz" has the same address whether it is in an array or stored in a variable:

    >>> a = ["xyz",2,"deer"]
    >>> id(a[0])
    43449600
    >>> b = a[0]
    >>> id(b)
    43449600
    

    It looks like you were expecting id() to give you the address of the pointers in the list, python does not provide any way to get this address but you can figure it out if you want.

    1. To start you would need to do id(a), which would give you the location of the list data structure, I'll use 4346000 as an example.
    2. The list data structure contains some standard python bookkeeping fields followed by the array of pointers that you are interested in. The size of the bookeeping fields depends on your system and python build but lets say it is 24 bytes.
    3. If you look past the bookkeeping at address 43460024 you would find your first pointer to 43449600
    4. Assuming 8 byte pointers the next element is at 43460032 and contains the pointer 1403048416
    5. The last at 43460040 you would find 43489824.

    Of course there is no good reason you would need those addresses. You can find more details about the of a list by seeing the struct definitionin the cpython headers.