Can someone explain this to me? So I\'ve been playing with the id() command in python and came across this:
>>> id(\'cat\')
5181152
>>> a = \'c
Python reuses string literals fairly aggressively. The rules by which it does so are implementation-dependent, but CPython uses two that I'm aware of:
"cat"
, it always refers to the same string object.
def foo(): return "pack my box with five dozen liquor jugs"
def bar(): return "pack my box with five dozen liquor jugs"
assert foo() is bar() # AssertionError
Both optimizations are done at compile time (that is, when the bytecode is generated).
On the other hand, something like chr(99) + chr(97) + chr(116)
is a string expression that evaluates to the string "cat"
. In a dynamic language like Python, its value can't be known at compile time (chr()
is a built-in function, but you might have reassigned it) so it normally isn't interned. Thus its id()
is different from that of "cat"
. However, you can force a string to be interned using the intern()
function. Thus:
id(intern(chr(99) + chr(97) + chr(116))) == id("cat") # True
As others have mentioned, interning is possible because strings are immutable. It isn't possible to change "cat"
to "dog"
, in other words. You have to generate a new string object, which means that there's no danger that other names pointing to the same string will be affected.
Just as an aside, Python also converts expressions containing only constants (like "c" + "a" + "t"
) to constants at compile time, as the below disassembly shows. These will be optimized to point to identical string objects per the rules above.
>>> def foo(): "c" + "a" + "t"
...
>>> from dis import dis; dis(foo)
1 0 LOAD_CONST 5 ('cat')
3 POP_TOP
4 LOAD_CONST 0 (None)
7 RETURN_VALUE