0Pricing
Python Academy · Lección

Conteo de referencias en CPython

Comprenda cómo CPython controla la vida útil de los objetos mediante recuentos de referencias.

Conteo de referencias en CPython es una lección gratuita de Python Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Python Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Python Academy incluye 4 lecciones en total.

¿Qué es el conteo de referencias?

CPython realiza un seguimiento del contador de referencias de cada objeto. Cuando el contador llega a 0, el objeto se desasigna inmediatamente. Este es el mecanismo principal de gestión de memoria de Python.

import sys

x = [1, 2, 3]
print(sys.getrefcount(x))   # 2 (x + getrefcount arg)
y = x
print(sys.getrefcount(x))   # 3

sys.getrefcount()

sys.getrefcount(obj) devuelve el contador de referencias actual. Nota: llamarlo añade 1 (la referencia del argumento de la función).

import sys

a = "hello"
print(sys.getrefcount(a))   # baseline (may be high for interned strings)

b = a
print(sys.getrefcount(a))   # one more
del b
print(sys.getrefcount(a))   # back to baseline

Incremento y decremento

Cada asignación incrementa el contador; cada eliminación o reasignación lo decrementa. Cuando el contador llega a 0, CPython llama al desasignador del objeto.

x = []          # refcount = 1
y = x           # refcount = 2
z = [x]         # refcount = 3  (list holds a reference)
del y           # refcount = 2
z.clear()       # refcount = 1
del x           # refcount = 0 → deallocated

Internamiento de objetos

CPython interna los enteros pequeños (de -5 a 256) y muchos literales de cadena, reutilizando el mismo objeto. Las comparaciones con is permiten observarlo.

a = 256
b = 256
print(a is b)   # True (interned)

c = 257
d = 257
print(c is d)   # may be False (not interned)

Referencias débiles

Las referencias débiles no incrementan el contador de referencias. Son útiles para evitar impedir la recolección de basura de objetos que quiere observar, pero no poseer.

import weakref

class BigObject:
    pass

obj = BigObject()
ref = weakref.ref(obj)
print(ref())   # <BigObject instance>
del obj
print(ref())   # None (object was collected)

Ciclos de referencias

Si A hace referencia a B y B hace referencia a A, ninguno llega a 0 aunque ambos sean inaccesibles. El GC cíclico de CPython detecta y recopila estos ciclos.

a = []
b = [a]
a.append(b)   # cycle: a → b → a
del a, b
# Both are unreachable but refcount > 0
# The cyclic GC collects them

El módulo gc

El módulo gc proporciona el recolector de basura cíclico. Se ejecuta automáticamente, pero también puede activarse manualmente o deshabilitarse.

import gc

gc.collect()   # force a collection cycle
print(gc.get_count())    # (gen0, gen1, gen2) allocation counts
print(gc.get_threshold())  # when each generation is collected

Pools de memoria (pymalloc)

CPython asigna los objetos pequeños (< 512 bytes) desde su propio pool de memoria (pymalloc), que es más rápido que llamar a malloc para cada objeto pequeño.

# You do not call pymalloc directly — CPython uses it internally
# for all Python-level object allocations

# The pool pre-allocates large memory arenas
# and carves them into pools of fixed-size blocks

Finalizadores __del__

__del__ se llama cuando el contador de referencias de un objeto llega a 0 (o más tarde si forma parte de un ciclo). Evite depender de él para la limpieza crítica; use gestores de contexto.

class Resource:
    def __del__(self):
        print(f"Freeing {self}")

# Better: use context manager
class SafeResource:
    def __enter__(self): return self
    def __exit__(self, *a): self.cleanup()

Objetos compactos con __slots__

Los objetos con __slots__ utilizan menos memoria y requieren menos asignaciones, lo que reduce la presión sobre el GC.

import sys

class Reg:
    def __init__(self, x, y): self.x, self.y = x, y

class Slotted:
    __slots__ = ("x","y")
    def __init__(self, x, y): self.x, self.y = x, y

print(sys.getsizeof(Reg(1,2)))      # ~48 + dict overhead
print(sys.getsizeof(Slotted(1,2)))  # ~48 (no dict)

Deshabilitación del GC cíclico

En los programas que no crean ciclos de referencias, deshabilitar el GC cíclico puede mejorar el rendimiento.

import gc

gc.disable()   # no cyclic GC — objects are only freed by refcounting

# Use only if you KNOW no cycles are created
# (pure functional/immutable data)

gc.enable()    # re-enable

Comprobación rápida

¿Cuándo desasigna CPython inmediatamente un objeto?

Recapitulación

CPython realiza un seguimiento de los objetos mediante contadores de referencias. Cuando el contador llega a 0, se produce una desasignación inmediata. El GC cíclico gestiona los ciclos de referencias (módulo gc). Evite __del__ para la limpieza crítica; use gestores de contexto. Use __slots__ para reducir la memoria de cada objeto.

Preguntas frecuentes

¿La lección «Conteo de referencias en CPython» es gratis?

Sí — el texto completo de «Conteo de referencias en CPython» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Python Academy, actualiza a CoddyKit PRO. El curso de Python Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Conteo de referencias en CPython»?

Comprenda cómo CPython controla la vida útil de los objetos mediante recuentos de referencias. Practicas Python Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Python Academy?

No se requiere experiencia previa. Python Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Conteo de referencias en CPython»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Python Academy?

Sí. Cada lección de Python Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Conteo de referencias en CPython
  2. El recolector de basura y las referencias cíclicas
  3. Perfilado con cProfile y line_profiler
  4. Perfilado de memoria con tracemalloc
← Volver a Python Academy