1

I am currently using python 3.6, and I was playing around with the id() function. When I run the following code in IDLE,

x = 1

print(id(x), id(1))

The two memory addresses are the same. (1499456272 for me) My understanding is the integer 1, which is an object, has a memory address, and when the object is assigned to x, the variable gains the same memory address of the object. (not sure if this is correct)

When I replicate the above code using a string, for instance

s = "a"

print(id(s), id("a"))

I also get two memory addresses which are the same. Again, my current reasoning for why this occurs is the same as above.

However, when I try this using lists, I don't get the same memory address. For example,

l = [1]

print(id(l), id([1]))

gives me 1499456272 and 67146456.

Can anyone explain to me why this occurs? Perhaps my current reasoning for why ints and strings have the same memory address is flawed. Thanks :D

zekai123
  • 11
  • 1
  • 2
  • There is no such thing as a "variable" in Python in the classic (C) sense. Everything is objects all the way down. – Ignacio Vazquez-Abrams Jun 11 '18 at 19:56
  • It has nothing to do with variables, it's simply that CPython always reuses the same int object for the value 1 and the string `"a"`, but it doesn't do that for lists. The problem can be reduced to `1 is 1` returning True and `[] is []` returning False, because those two lists aren't the same list instance. – Aran-Fey Jun 11 '18 at 20:06
  • -5 to 256 are cached: same id: https://docs.python.org/3/c-api/long.html#c.PyLong_FromLong – Patrick Artner Jun 11 '18 at 20:20

1 Answers1

1

cPython interns all integers from -5 to 256 as well as string literals. This means whenever you get such a value, Python knows it has a copie of it in memory and returns the same object.

Although, the way this happens is different for both types.

For integers, those values are always interned, allowing the process to be dynamic.

On the other hand, string interning happens at compilation and thus is specific to string literals.

We can do some experiment with is which is equivalent to comparing id of live objects.

x = 1 + 1
y = 3 - 1
x is y # True

x = 'b'
y = 'b'
x is y # True

x = 257
y = 257
x is y # False

x = 'ab'.replace('a', '')
y = 'b'
x is y # False

Although, this is not the case for objects of other types, such as list, namely because they are mutable, so you absolutely would not want the same object to be returned.

[] is [] # False

Although, the bottom line is that this is an optimisation implementation and you should not rely on it in your code. In general, assume that different expressions return different objects, for the above are exceptions.

Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73