to the object when called):
```pycon
- >>> x = object()
- >>> sys.getrefcount(x)
- 2
- >>> y = x
- >>> sys.getrefcount(x)
- 3
- >>> del y
- >>> sys.getrefcount(x)
- 2
+>>> x = object()
+>>> sys.getrefcount(x)
+2
+>>> y = x
+>>> sys.getrefcount(x)
+3
+>>> del y
+>>> sys.getrefcount(x)
+2
```
The main problem with the reference counting scheme is that it does not handle reference
cycles. For instance, consider this code:
```pycon
- >>> container = []
- >>> container.append(container)
- >>> sys.getrefcount(container)
- 3
- >>> del container
+>>> container = []
+>>> container.append(container)
+>>> sys.getrefcount(container)
+3
+>>> del container
```
In this example, `container` holds a reference to itself, so even when we remove
unreachable:
```pycon
- >>> import gc
-
- >>> class Link:
- ... def __init__(self, next_link=None):
- ... self.next_link = next_link
-
- >>> link_3 = Link()
- >>> link_2 = Link(link_3)
- >>> link_1 = Link(link_2)
- >>> link_3.next_link = link_1
- >>> A = link_1
- >>> del link_1, link_2, link_3
-
- >>> link_4 = Link()
- >>> link_4.next_link = link_4
- >>> del link_4
-
- # Collect the unreachable Link object (and its .__dict__ dict).
- >>> gc.collect()
- 2
+>>> import gc
+>>>
+>>> class Link:
+... def __init__(self, next_link=None):
+... self.next_link = next_link
+...
+>>> link_3 = Link()
+>>> link_2 = Link(link_3)
+>>> link_1 = Link(link_2)
+>>> link_3.next_link = link_1
+>>> A = link_1
+>>> del link_1, link_2, link_3
+>>>
+>>> link_4 = Link()
+>>> link_4.next_link = link_4
+>>> del link_4
+>>>
+>>> # Collect the unreachable Link object (and its .__dict__ dict).
+>>> gc.collect()
+2
```
The GC starts with a set of candidate objects it wants to scan. In the
function:
```pycon
- >>> import gc
- >>> gc.get_threshold()
- (700, 10, 10)
+>>> import gc
+>>> gc.get_threshold()
+(700, 10, 10)
```
The content of these generations can be examined using the
specifically in a generation by calling `gc.collect(generation=NUM)`.
```pycon
- >>> import gc
- >>> class MyObj:
- ... pass
- ...
-
- # Move everything to the old generation so it's easier to inspect
- # the young generation.
-
- >>> gc.collect()
- 0
-
- # Create a reference cycle.
-
- >>> x = MyObj()
- >>> x.self = x
-
- # Initially the object is in the young generation.
-
- >>> gc.get_objects(generation=0)
- [..., <__main__.MyObj object at 0x7fbcc12a3400>, ...]
-
- # After a collection of the youngest generation the object
- # moves to the old generation.
-
- >>> gc.collect(generation=0)
- 0
- >>> gc.get_objects(generation=0)
- []
- >>> gc.get_objects(generation=1)
- []
- >>> gc.get_objects(generation=2)
- [..., <__main__.MyObj object at 0x7fbcc12a3400>, ...]
+>>> import gc
+>>> class MyObj:
+... pass
+...
+>>> # Move everything to the old generation so it's easier to inspect
+>>> # the young generation.
+>>> gc.collect()
+0
+>>> # Create a reference cycle.
+>>> x = MyObj()
+>>> x.self = x
+>>>
+>>> # Initially the object is in the young generation.
+>>> gc.get_objects(generation=0)
+[..., <__main__.MyObj object at 0x7fbcc12a3400>, ...]
+>>>
+>>> # After a collection of the youngest generation the object
+>>> # moves to the old generation.
+>>> gc.collect(generation=0)
+0
+>>> gc.get_objects(generation=0)
+[]
+>>> gc.get_objects(generation=1)
+[]
+>>> gc.get_objects(generation=2)
+[..., <__main__.MyObj object at 0x7fbcc12a3400>, ...]
```
tracking status of the object.
```pycon
- >>> gc.is_tracked(0)
- False
- >>> gc.is_tracked("a")
- False
- >>> gc.is_tracked([])
- True
- >>> gc.is_tracked(())
- False
- >>> gc.is_tracked({})
- True
- >>> gc.is_tracked({"a": 1})
- True
+>>> gc.is_tracked(0)
+False
+>>> gc.is_tracked("a")
+False
+>>> gc.is_tracked([])
+True
+>>> gc.is_tracked(())
+False
+>>> gc.is_tracked({})
+True
+>>> gc.is_tracked({"a": 1})
+True
```
Differences between GC implementations