5

Under Python 2.7.5

>>> import sys
>>> sys.getrefcount(10000)
3

Where are the three refcount?

PS: when the 10000 PyIntObject would be Py_DECREF to 0 ref and deallocated? Do not say about gc stuff, reference count itself can work without gc.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
fengsp
  • 1,035
  • 1
  • 11
  • 19
  • [**This previously asked question**](http://stackoverflow.com/questions/10302133/why-does-sys-getrefcount-return-2) might solve your problem... Apparently `sys.getrefcount()` always returns one more than the expected value. –  Mar 21 '14 at 03:49
  • That would be 2, I got 3 – fengsp Mar 21 '14 at 03:57
  • Possible duplicate of ["sys.getrefcount()" return value](http://stackoverflow.com/questions/7544395/sys-getrefcount-return-value) – ederag Jan 23 '16 at 11:28

1 Answers1

7
  1. When you do something in the REPL console, the string will be compiled internally and during the compilation process, Python creates an intermediate list with the list of strings apart from tokens. So, that is reference number 1. You can check this like this

    import gc
    print gc.get_referrers(10000)
    # [['sys', 'dis', 'gc', 'gc', 'get_referrers', 10000], (-1, None, 10000)]
    
  2. Since its just a numeral, during the compilation process, peep-hole optimizer of Python, stores the number as one of the constants in the generated byte-code. You can check this like this

    print compile("sys.getrefcount(10000)", "<string>", "eval").co_consts
    # (10000,)
    

Note:

The intermediate step where Python stores 10000 in the list is only for the string which is compiled. That is not generated for the already compiled code.

print eval("sys.getrefcount(10000)")
# 3
print eval(compile("sys.getrefcount(10000)", "<string>", "eval"))
# 2

In the second example, we compile the code with the compile function and pass only the code object to the eval function. Now there are only two references. One is from the constant created by the peephole optimizer, the other is the one in sys.getrefcount.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • But, why do I get the same thing when I put this in a file and run `python test.py`? Wouldn't that take me out of the REPL? – mgilson Mar 21 '14 at 05:20
  • You mean why you are getting 3? – thefourtheye Mar 21 '14 at 05:21
  • Yes, that's the question of the night :) – mgilson Mar 21 '14 at 05:22
  • @mgilson That is because, it still has to [parse](http://hg.python.org/cpython/file/3a1db0d2747e/Python/pythonrun.c#l1348) and [compile](http://hg.python.org/cpython/file/3a1db0d2747e/Python/pythonrun.c#l1367) the file – thefourtheye Mar 21 '14 at 05:38
  • @mgilson You might want to see this [ASCII Cinema](https://asciinema.org/a/8320) as well. Here, I straight away execute the file and I get 3. I compile it and execute the bytecode, I get 2. – thefourtheye Mar 21 '14 at 05:46
  • Ahh yes. I believe you now -- Or maybe just that I _understand_ it now ... :). Brilliant. I love these questions because every time I end up digging a little deeper into the source code -- Generally it doesn't help, but at least I get a little more familiar with the code (and learn something when someone smarter than I figures out the actual answer) – mgilson Mar 21 '14 at 05:51
  • @thefourtheye One more question, as I asked, when exactly would the refcount down to 0, or when the code object would not hold 10000 anymore, inside Python source code, which part handle it? – fengsp Mar 21 '14 at 06:10
  • @fsp The reference count for the constants in byte code, will not drop to 0 till the execution of the program is completed. Normally, [`Py_INCREF`](http://hg.python.org/cpython/file/3a1db0d2747e/Include/object.h#l765) and [`Py_DECREF`](http://hg.python.org/cpython/file/3a1db0d2747e/Include/object.h#l769) will increment and decrement the reference counts. – thefourtheye Mar 21 '14 at 07:21