Search code examples
pythonpython-2.7python-3.xcpython

Difference in variable allocation in python interpreter and python program


I run the below code in python interpreter

Python 2.7.12 (default, Sep 20 2016, 14:42:48)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> x = 300
>>> y = 300
>>> id(x)
140510001982256
>>> id(y)
140510001982160

And then I write a small program and run it:

Program :

 x = 15000
 y = 15000

 if __name__ == "__main__":
     print (id(x))
     print (id(y))

Output:

$ python mem_test.py
140525354104776
140525354104776

What is the reason for this ?


Solution

  • An object id is an implementation-defined "blackbox" value. The only garantees are that a given object will keep the same id for all it's lifetime and that no other object (in the same process...) will share this id during this same time (but the id can be reused for another object in the same process one the first object has been garbage collected).

    Note that the implementation is free to cache immutable objects for performance reasons, and CPython has indeed been caching some immutable objects under certain circonstances - notably "small" integers (for a definition of "small" that has changed from version to version) and strings that could be valid variables/functions/classes/modules names, but this is really just an implementation detail. FWIW, it looks like some of this caching is not happening at the REPL's top-level anymore (if it ever happened here) - but it still happens in functions defined in the REPL:

    Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
    [GCC 4.8.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    pythonrc start
    pythonrc done
    >>> x = 300
    >>> y = 300
    >>> id(x)
    37126296
    >>> id(y)
    37126248
    >>> def foo():
    ...    x = 300; print "id(x): %s" % id(x)
    ...    y = 300; print "id(y): %s" % id(y)
    ... 
    >>> foo()
    id(x): 37126200
    id(y): 37126200
    >>> foo()
    id(x): 37126200
    id(y): 37126200
    >>> foo()
    id(x): 37126200
    id(y): 37126200
    >>> id(x)
    37126296
    >>> id(y)
    37126248
    

    To make a long story short: you shouldn't ever care about this (unless you're writing your own python runtime of course).