0

I was wondering why the following happens in Python:

a=[1,2]
id(a)=2228192243968
id([1,2])=2228187169104

I tried the same with integers and got the expected result:

a=1
id(a)=2228187169008
id(1)=2228187169008
Bart Kiers
  • 166,582
  • 36
  • 299
  • 288
mathboi
  • 3
  • 2
  • This is my assumption, so please try to verify my insight. a list is not a primitive class, thus `a` contains the pointer of the list and not the list itself, thus the difference between the ids. in fact, if you manage to find the implementation of the class list, you will find that the `__str__` method is overridden to print the list. if that function was not defined in the class. printing the variable `a` will show you the address of the object (the list in this case)! – Wissem Rouin Feb 21 '23 at 22:17
  • 3
    @WissemRouin there are no "primitive" classes in Python. And it doesn't have pointers. Everything is a *full fledged object*. `list` objects are just as much objects as `int` objects. It is just a Cpython implementation detail that small integers (-5 to 255 IIRC) are cached. Both have a `__str__` method that is printing *something*. `int` and `list` both have the same situation going on, a `__str__` method that prints a useful representation of the object. If that function were not defined, then they would both inherit `object.__str__`. – juanpa.arrivillaga Feb 21 '23 at 22:23
  • 1
    "got the expected result:" **why was that your expected result**? If anything, that should be the **unexpected result**. If you don't actually explain why you expected something, we cannot really clarify effectively for you. But suffice it to say, `id` is working properly in both cases -- it is giving you a unique (for the lifetime of the object) integer. In the `list` case, the second literal expression creates a new list object. It must do this. In the `int` case, it doesn't. The runtime is free to do that because `int` objects are immutable – juanpa.arrivillaga Feb 21 '23 at 22:23
  • 3
    If two lists became the same object simply because they happened to contain the same contents at some moment in time, then lists would be *COMPLETELY USELESS FOR ANY PURPOSE* - you could never be sure that some other code hadn't created such a coincidental duplicate, and had possibly modified the now-shared list. Immutable objects such as integers have no such concern, since no other code can modify them even if they have a shared reference to them. – jasonharper Feb 21 '23 at 22:25
  • @juanpa.arrivillaga well noted, thanks for the correction. but if you can do me a favor and explain to me what the does object.__str__ print. because when creating a class without defining the __str__ method, i remember that typing an object of the class in the terminal returns address like output! i know that i can't use pointers in python but i want to verify that that output is an address. – Wissem Rouin Feb 21 '23 at 22:36
  • 1
    @WissemRouin the ouput contains an address, but not just an "address". It is a *string*, not an integer (which would make it a bad address). Essentially, you can think if it as implemented like `return f"<{type(self).__qualname__} at {hex(id(self))}>"` – juanpa.arrivillaga Feb 21 '23 at 22:43
  • 1
    @WissemRouin although, checking now, `object.__str__` returns the pretty list representation! Probably due to how it is all implemented under the hood, but note, what `object.__repr__([1,2,3])` gives you – juanpa.arrivillaga Feb 21 '23 at 22:46
  • @juanpa.arrivillaga Well explained ! thank you ^_^ – Wissem Rouin Feb 21 '23 at 22:51
  • 1
    @WissemRouin ah, here is what's going on. Here is the generic `object.__str__`: https://github.com/python/cpython/blob/d5c7954d0c3ff874d2d27d33dcc207bb7356f328/Objects/object.c#L440 Essentially, if the object doesn't define a `__str__`, it defers to `__repr__`: `if (Py_TYPE(v)->tp_str == NULL): return PyObject_Repr(v);`. Which is the case for `list` (check for yourself: `"__str__" in vars(list)` gives `False`). However, it does define a `__repr__`, which is the one we know and love! – juanpa.arrivillaga Feb 21 '23 at 22:51
  • 1
    @WissemRouin also, here is where the default `__repr__` string is constructed in the C source: https://github.com/python/cpython/blob/d5c7954d0c3ff874d2d27d33dcc207bb7356f328/Objects/object.c#L400 – juanpa.arrivillaga Feb 21 '23 at 22:54
  • That was mind blowing, i have never had the idea to check the source code TBH. that explains it all ! – Wissem Rouin Feb 21 '23 at 23:04

0 Answers0