import sys
a = [1, 2, 3]
print(sys.getrefcount(a)) # 2 (a + temporary arg)
b = a
print(sys.getrefcount(a)) # 3 (a, b, temporary)
del b
print(sys.getrefcount(a)) # 2
del a # refcount → 0, memory freed immediatelyimport gc
import sys
class Node:
def __init__(self, name):
self.name = name
self.ref = None
def __repr__(self):
return f'Node({self.name})'
# Create a reference cycle
a = Node('A')
b = Node('B')
a.ref = b
b.ref = a
print(sys.getrefcount(a)) # Still referenced!
del a
del b
# Refcount never reaches 0 — cycle!
# But GC handles it
collected = gc.collect()
print(f'Collected {collected} objects') # 2import gc
print(f'GC enabled: {gc.isenabled()}')
gc.disable()
print(f'GC enabled: {gc.isenabled()}')
gc.enable()
# Force collection
gc.collect()
# Get garbage objects (unreachable with cycles)
print(f'Garbage count: {len(gc.garbage)}')
# Set debug flags
gc.set_debug(gc.DEBUG_STATS)import sys
# Object sizes
print(sys.getsizeof(0)) # 28 bytes
print(sys.getsizeof('hello')) # 54 bytes
print(sys.getsizeof([1,2,3])) # 88 bytes
print(sys.getsizeof({})) # 64 bytes
print(sys.getsizeof(())) # 40 bytes (tuple is smaller than list!)
# Tracing memory allocations
import tracemalloc
tracemalloc.start()
# Allocate memory
data = [list(range(1000)) for _ in range(100)]
# Get current memory snapshot
snapshot = tracemalloc.take_snapshot()
for stat in snapshot.statistics('lineno')[:3]:
print(stat)
tracemalloc.stop()class Resource:
def __init__(self, name):
self.name = name
print(f'{self.name} created')
def __del__(self):
print(f'{self.name} destroyed')
r = Resource('MyResource')
# 'MyResource created'
del r
# 'MyResource destroyed'
# Warning: __del__ not guaranteed to run!
# Use context managers instead for reliable cleanup# Small integers are interned (-5 to 256)
a = 100
b = 100
print(a is b) # True (same object!)
a = 300
b = 300
print(a is b) # False (different objects!)
# Short strings may be interned
a = 'hello'
b = 'hello'
print(a is b) # True (implementation detail, don't rely on it!)
# Force interning
import sys
a = sys.intern('a_very_long_string_that_wouldnt_normally_be_interned')
b = sys.intern('a_very_long_string_that_wouldnt_normally_be_interned')
print(a is b) # TrueCreate a `Node` class with `name` and `ref` attributes. Create a reference cycle (A.ref = B, B.ref = A), delete both variables, then use `gc.collect()` to clean up and print how many objects were collected. Use `sys.getrefcount()` to demonstrate refcount changes when creating and deleting references. Use `sys.getsizeof()` to compare sizes of list vs tuple vs set with the same elements. Use `tracemalloc` to measure memory before and after creating a large list.