python garbage collection and _ underscore in inte

2019-06-05 02:58发布

If a class is defined in interpreter environment:

class C(object):
    def __init__(self, val):
        self.x = val

Then instantiated without names:

>>> C(1)
>>> C(2)
>>> 

Then we can use underscore _ to refer to C(2), so here is my question:

  • Since the underscore '_' refer to C(2), can we say the reference counter for C(2) is still 1? So the python gc will not free the memory taken by C(2)?
  • As far as I know, after these C(2) is executed, no names will refer to C(1), so can I say as soon as C(2) is executed, C(1)'s memory will be freed by python gc?

These are actually 4 questions, one bold font to one.

gc: short for garbage collection

EDIT

Let me make my first question more clear by commenting directly into the codes.

>>> C(1) # Press Enter Key and run
>>> 
>>> At Here, what is the exact reference count for the previous anonymous object "C(1)"? 
>>> And how to prove?
>>> 
>>> C(2) # Press Enter Key and run
>>> 
>>> At Here, what is the exact reference count for the previous anonymous object "C(1)"?
>>> And how to prove?

2条回答
我命由我不由天
2楼-- · 2019-06-05 03:42

C(1) or C(2) as last line of the interpreter behaves differently when they are in the middle or to the up of the code.

If C(1) is at the last line, python interpreter will store it as <__main__.C object at 0x00000000********>, so actually it will have a name attached to it. If you check number_of_instances(C), the result will be 1.

If C(1) is not at the last line, this temporary anonymous object is just destroyed and disappeared.

Check the following testing codes.

You can use number_of_instances to show if there is any C object resides in memory.

import gc

def name_of_instances(cls):
    return [obj for obj in gc.get_objects() if isinstance(obj, cls)]

def number_of_instances(cls):
    return len([obj for obj in gc.get_objects() if isinstance(obj, cls)])

1.anonymous object not at last line

In [12]: C(1)
    ...: C(2)
    ...: print(number_of_instances(C))
    ...:
0

In [13]:

2.anonymous object at last line

In [6]: C(1)
Out[6]: <__main__.C at 0x6a97ba8>

In [7]: print(number_of_instances(C))
   ...: print(name_of_instances(C))
   ...:
1
[<__main__.C object at 0x0000000006A97BA8>]

In [8]: C(2)
Out[8]: <__main__.C at 0x6a9b518>

In [9]: print(number_of_instances(C))
   ...: print(name_of_instances(C))
   ...:
2
[<__main__.C object at 0x0000000006A97BA8>, <__main__.C object at 0x0000000006A9B518>]

3.underscore _ will remember C(3) if it is the last line

In [13]: C(3)
Out[13]: <__main__.C at 0x6aa06d8>

In [14]: type(_)
Out[14]: __main__.C

But in this case, the reference counter never counts reference from _, it only counts <__main__.C object at 0x0000000006AA06D8> which you didn't observe.

A guess here: _ is not in gc.garbage list. If you run C(1), print(number_of_instances(C)) successively, number_of_instances will not check into _ which may be storing the previous C(1)

See: sys.getrefcount continuation

查看更多
相关推荐>>
3楼-- · 2019-06-05 03:45

@allen, thank you so much for your answer.

Based on your guess, I made the following code:

In [3]: {'a': 1}
Out[3]: {'a': 1}

In [4]: C(1)
   ...: print(_)
   ...: print(type(_))
   ...: print(number_of_instances(C))
   ...:
{'a': 1}
<class 'dict'>
0

In [5]:

So the _ underscore is only used for storing the value of last expression in interpreter of "Single Step Mode", not for "Continuous Mode".

This might be a common mistake made by beginners.

Anyway, thank you so much for your answer!

查看更多
登录 后发表回答