Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

La Programación Orientada a Objetos (POO) es un paradigma de programación que utiliza “objetos” para representar datos y comportamientos. En Python, la POO se implementa a través de clases e instancias de esas clases, los objetos.

Las clases permiten definir nuevos tipos de datos, encapsulando atributos (datos) y métodos (funciones) que operan sobre esos datos. Esto facilita la organización del código, la reutilización y la creación de programas más complejos de manera estructurada.

1Algunos conceptos clave de la POO

Atributos
Son variables que pertenecen a un objeto y representan su estado interno. Los atributos pueden ser de diferentes tipos, como enteros, cadenas, listas, otros objetos, etc. Cada objeto en memoria tiene sus propios valores para estos atributos. Estos atributos determinan el estado del objeto.
Métodos de instancia
Son funciones definidas en una clase que operan sobre los atributos del objeto (su estado interno).
Métodos de clase
Son métodos que pertenecen a la clase en sí, no a las instancias de la clase. Es decir, son funciones que pueden ser llamadas sin necesidad de crear un objeto de la clase. Al ejecutarse en el contexto de la clase, no tiene un vínculo con las instancias que se hayan creado.
Comportamiento
Se refiere al conjunto de métodos a los que puede responder un objeto. Los métodos definen cómo interactúa el objeto con otros objetos y cómo se comporta en diferentes situaciones.
Herencia
Permite que una clase herede atributos y métodos de otra clase, lo que facilita la reutilización de código y la creación de jerarquías de clases.
La clase que hereda se llama “subclase” o “clase derivada”, mientras que la clase de la que hereda se llama “superclase” o “clase base”. Python soporta herencia múltiple, lo que significa que una clase puede heredar de múltiples clases al mismo tiempo.
Constructor
Es un método especial que se llama automáticamente cuando se crea un objeto de la clase. La finalidad del constructor es inicializar los atributos del objeto.

2Clases y objetos

En Python, una clase es una plantilla para crear objetos, similar a los struct de Go, una clase permite definir nuevos tipos de datos. Un objeto, en cambio, es una instancia de una clase y puede tener atributos (datos) y métodos (funciones). Pueden existir múltiples objetos de la misma clase, cada uno con sus propios valores para los atributos.

class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

    def saludar(self):
        print(f"Hola, mi nombre es {self.nombre} y tengo {self.edad} años.")

Creamos un objeto de la clase Persona.

persona1 = Persona("Alice", 30)
persona1.saludar()
Output
Hola, mi nombre es Alice y tengo 30 años.

Si consultamos el tipo de persona1 veremos que es la clase Persona.

type(persona1)
Output
__main__.Persona

En el ejemplo de código anterior, se define una clase Persona con un constructor (__init__) que inicializa los atributos nombre y edad. También se define un método saludar que imprime un saludo. Luego, se crea un objeto persona1 de la clase Persona y se llama al método saludar.

El constructor en Python siempre es __init__ y se utiliza para inicializar los atributos del objeto. Si no se declara explícitamente, Python proporcionará un constructor por defecto que no hace nada.

3Herencia

Una clase puede heredar de otra clase, o dicho de otra manera, puede extender otra clase. Esto permite que una clase herede atributos y métodos de su ancestro, y los pueda utilizar directamente sin tener que declararlos nuevamente, lo que facilita la reutilización de código y la creación de jerarquías de clases.

class Docente(Persona):
    def __init__(self, nombre, edad, materia):
        super().__init__(nombre, edad)  # Llama al constructor de la clase base
        self.materia = materia

    def presentar(self):
        self.saludar()  # Usa método heredado
        print(f"Soy docente de {self.materia}.")

Creamos un objeto de la clase Docente.

docente1 = Docente("Juan", 25, "Algoritmos y Programación")
docente1.presentar()
Output
Hola, mi nombre es Juan y tengo 25 años.
Soy docente de Algoritmos y Programación.

También podemos consultar su tipo.

type(docente1)
Output
__main__.Docente

En el ejemplo anterior, la clase Docente hereda de la clase Persona. Es decir un Docente es una Persona y por lo tanto tiene todos los atributos y métodos de cualquier Persona y además tiene nuevos atributos y métodos como Docente.

El constructor de la clase Docente espera todos los parámetros para poder instanciar un nuevo objeto del tipo Docente, esto es el nombre y la edad de la Persona y la materia de la que es Docente.

Lo primero que hace el constructor de la clase Docente es llamar al constructor de la clase base Persona utilizando super().__init__(nombre, edad) Esto asegura que los atributos nombre y edad se inicialicen correctamente en el objeto Docente.

super() es una función que permite llamar a métodos de la clase base desde una subclase. Cuando se invoca super().__init__(nombre, edad), se está llamando al constructor de la clase base Persona.

En este caso como tanto Docente como Persona tienen un constructor, __init__, es necesario usar super() para llamar al constructor de la clase base, caso contrario, se estaría llamando al constructor de la clase Docente.

Con esta estrategia se evita la duplicación de código y se asegura que los atributos de la clase base se inicialicen correctamente. Además, si por algún motivo hay que modificar el constructor de la clase base, no es necesario cambiar el código de la subclase.

En el método presentar, se llama al método saludar de la clase base Persona utilizando self.saludar(), lo que permite reutilizar el comportamiento definido en la clase base. En este caso como el método saludar no fue sobreescrito en la clase Docente, directamente se puede utilizar self.saludar() para llamar al método de la clase base, sin problemas.

3.1Herencia múltiple

Python va más allá que otros lenguajes de programación orientados a objetos y permite la herencia múltiple, lo que significa que una clase puede heredar de múltiples clases al mismo tiempo. Esto se logra especificando múltiples clases base en la definición de la clase.

class Persona:
    def __init__(self, nombre, edad):
        self.nombre = nombre
        self.edad = edad

    def saludar(self):
        print(f"Hola, mi nombre es {self.nombre} y tengo {self.edad} años")


class Docente(Persona):
    def __init__(self, legajo, nombre, edad, materia):
        Persona.__init__(self, nombre, edad)
        self.legajo = legajo  # legajo del Docente como Empleado
        self.materia = materia

    def presentar(self):
        self.saludar()
        print(f"Soy docente de {self.materia}")

    def pagar(self):
        print(f"Pago realizado al docente {self.nombre}, "
              f"con legajo {self.legajo}.")


class Estudiante(Persona):
    def __init__(self, legajo, nombre, edad, carrera):
        Persona.__init__(self, nombre, edad)
        self.legajo = legajo  # legajo del Estudiante como Alumno
        self.carrera = carrera

    def presentar(self):
        self.saludar()
        print(f"Soy estudiante de {self.carrera}")

    def mostrar_legajo(self):
        print(f"Legajo: {self.legajo}, Nombre: {self.nombre}.")

    def actualizar_legajo(self, nuevo_legajo):
        self.legajo = nuevo_legajo
        print(f"Legajo actualizado a: {self.legajo}")


class Ayudante(Estudiante, Docente):
    def __init__(self, legajo, nombre, edad, materia, carrera):
        Estudiante.__init__(self, legajo, nombre, edad, carrera)
        Docente.__init__(self, legajo, nombre, edad, materia)

    def presentar(self):
        self.saludar()
        print(f"Soy estudiante de {self.carrera} y ayudante en "
              f"{self.materia}")

Creamos un objeto de la clase Docente.

docente1 = Docente(64781, "Juan", 30, "Algoritmos y Programación")
docente1.presentar()
Output
Hola, mi nombre es Juan y tengo 30 años
Soy docente de Algoritmos y Programación

Creamos un objeto de la clase Estudiante.

estudiante1 = Estudiante(30415, "Ana", 20, "Ingeniería en Computación")
estudiante1.presentar()
Output
Hola, mi nombre es Ana y tengo 20 años
Soy estudiante de Ingeniería en Computación

Creamos un objeto de la clase Ayudante.

ayudante1 = Ayudante(
    29478, "Luis", 23, "Algoritmos y Programación", "Ingeniería en Sonido"
)
ayudante1.presentar()
Output
Hola, mi nombre es Luis y tengo 23 años
Soy estudiante de Ingeniería en Sonido y ayudante en Algoritmos y Programación
type(ayudante1)
Output
__main__.Ayudante
print("Pagar a docentes")

for docente in [docente1, ayudante1]:
    docente.pagar()
Output
Pagar a docentes
Pago realizado al docente Juan, con legajo 64781.
Pago realizado al docente Luis, con legajo 29478.
print("Mostrar legajo de estudiantes")

for estudiante in [estudiante1, ayudante1]:
    estudiante.mostrar_legajo()
Output
Mostrar legajo de estudiantes
Legajo: 30415, Nombre: Ana.
Legajo: 29478, Nombre: Luis.

Actualizamos el legajo del ayudante

ayudante1.actualizar_legajo(12345)
ayudante1.pagar()
Output
Legajo actualizado a: 12345
Pago realizado al docente Luis, con legajo 12345.

Hemos definido cuatro clases: Persona, Docente, Estudiante y Ayudante. Docente y Estudiante heredan de Persona, mientras que Ayudante hereda de Estudiante y Docente a través de la herencia múltiple. Lo que le permite a un Ayudante heredar el comportamiento de ambas clases además de sumar sus propios atributos y métodos.

En el siguiente diagrama de clases se puede observar la relación entre las clases y los atributos y métodos de cada una.

Diagrama de clases de Ayudante

Diagrama de clases de Ayudante

Diagrama de clases de Ayudante

Diagrama de clases de Ayudante

Cuando hay herencia múltiple se recomienda utilizar el nombre de la clase base explícitamente en el constructor de la subclase en lugar de super(). En la clase Docente, se utiliza directamente Persona en lugar de usar super(), y en la clase Estudiante también, para evitar ambigüedades en la resolución de métodos y atributos.

En el ejemplo anterior, tanto Docente como Estudiante tienen un atributo legajo, por lo que al crear un objeto de la clase Ayudante, se debe especificar explícitamente a qué clase base se está llamando.

Ayudante hereda de ambas clases que tienen un atributo legajo, sin embargo el atributo legajo no se duplica en un objeto de la clase Ayudante. Lo que permite que con el mismo legajo de Estudiante se pueda pagar al Docente.

El siguiente fragmento de código inspecciona los atributos del objeto ayudante1 y los imprime en la consola (En Instrospección veremos más en detalle como los objetos pueden observarse y modificarse a sí mismos en tiempo de ejecución)

print("Atributos de ayudante1:")

atributos = vars(ayudante1)

for key, value in atributos.items():
    print(f"\t- {key}: {value}")
Output
Atributos de ayudante1:
	- nombre: Luis
	- edad: 23
	- legajo: 12345
	- carrera: Ingeniería en Sonido
	- materia: Algoritmos y Programación

4Polimorfismo

El polimorfismo es un concepto clave en la POO que permite que diferentes clases implementen métodos con el mismo nombre, pero con comportamientos diferentes. Esto significa que se puede tratar a objetos de diferentes clases de manera uniforme, utilizando el mismo nombre de método.

En el ejemplo anterior el método presentar se define tanto en Docente como en Estudiante. La clase Ayudante hereda ambos métodos y además lo sobreescribe.

Cuando hay herencia múltiple se debe tener cuidado como se resuelve el polimorfismo, ya que puede haber ambigüedades si dos clases base tienen un método con el mismo nombre. En Python, se utiliza el Orden de Resolución de Métodos (MRO) para determinar qué método se llama en caso de ambigüedad.

print("Orden de Resolución de Métodos (MRO) de Ayudante:")

orden = Ayudante.__mro__

for cls in orden:
    print(f"\t- {cls.__name__}")
Output
Orden de Resolución de Métodos (MRO) de Ayudante:
	- Ayudante
	- Estudiante
	- Docente
	- Persona
	- object

Es decir cuando un objeto de la clase Ayudante invoca a un método, Python primero busca el método en la propia clase Ayudante, luego en Estudiante, luego en Docente, luego en Persona y finalmente en object.

Por eso no se puede usar super() en el constructor de la clase Estudiante ya que si se hiciera, se generaría una ambigüedad en la resolución del método a llamar, ya que super() buscaría el siguiente método en la jerarquía de clases, que en este caso sería el constructor de Docente. Por lo tanto, se debe usar el nombre de la clase base explícitamente en el constructor de la subclase.

4.1Duck typing

El duck typing es un concepto en Python que se basa en la idea de que el tipo de un objeto se determina por su comportamiento en lugar de su clase. Es decir, si un objeto tiene los métodos y atributos necesarios para realizar una tarea, se puede tratar como si fuera de un tipo específico, sin necesidad de verificar su clase.

“Si camina como un pato, nada como un pato y grazna como un pato, entonces probablemente sea un pato.”

Principio fundamental del duck typing en Python

Este concepto es muy poderoso en Python, ya que permite que diferentes objetos puedan ser utilizados de manera intercambiable si cumplen con la interfaz esperada, sin necesidad de heredar de una clase específica. Todo ocurre de manera implícita, sin necesidad de declarar explícitamente que un objeto es de un tipo específico y sin necesidad de especificar interfaces o clases abstractas como en Java o Go. Esta versatilidad es gracias al sistema de tipos dinámico de Python.

4.2Ejemplo

En el siguiente ejemplo, cuyo diagrama de clases se muestra a continuación. Primero se define Punto que representa un punto en el plano cartesiano y luego se definen las Figuras Geométricas Cuadrado, Punto, Elipse y Punto que están compuestas por Punto. Cada figura tiene un método area que calcula su área, pero cada figura lo implementa de manera diferente.

Diagrama de clases de Figuras Geométricas

Diagrama de clases de Figuras Geométricas

Diagrama de clases de Figuras Geométricas

Diagrama de clases de Figuras Geométricas

main.py
"""
Demostración de polimorfismo con figuras geométricas.

Este módulo muestra cómo diferentes tipos de figuras pueden ser
tratadas de manera uniforme gracias al polimorfismo de Python.
"""

from punto import Punto
from rectangulo import Rectangulo
from cuadrado import Cuadrado
from circulo import Circulo
from elipse import Elipse
from triangulo import Triangulo


def imprimir_propiedades_figura(figura):
    """
    Imprime las propiedades de una figura usando polimorfismo.

    Args:
        figura: Cualquier objeto que tenga métodos perimetro() y area().
    """
    print(f"Figura: {figura}")
    print(f"  Perímetro: {figura.perimetro():.2f}")
    print(f"  Área: {figura.area():.2f}")
    print()


def demo_polimorfismo():
    """
    Demostración de polimorfismo con una lista de diferentes figuras.
    """
    print("=== Demostración de Polimorfismo con Figuras ===\n")

    # Crear diferentes tipos de figuras
    figuras = [
        # Rectángulo de 3x4
        Rectangulo(Punto(0, 0), Punto(3, 4)),
        # Cuadrado de lado 5
        Cuadrado(Punto(1, 1), 5),
        # Círculo de radio 3
        Circulo(Punto(2, 2), 3),
        # Elipse con radios 4 y 2
        Elipse(Punto(0, 0), 4, 2),
        # Triángulo rectángulo
        Triangulo(Punto(0, 0), Punto(3, 0), Punto(0, 4)),
        # Triángulo equilátero aproximado
        Triangulo(Punto(0, 0), Punto(2, 0), Punto(1, 1.732)),  # altura ≈ √3
    ]

    # Demostrar polimorfismo: mismo código funciona para todas las figuras
    total_perimetro = 0
    total_area = 0

    for i, figura in enumerate(figuras, 1):
        print(f"--- Figura {i} ---")
        imprimir_propiedades_figura(figura)

        # Acumular totales
        total_perimetro += figura.perimetro()
        total_area += figura.area()

    # Mostrar totales
    print("=" * 50)
    print(f"Total de figuras: {len(figuras)}")
    print(f"Perímetro total: {total_perimetro:.2f}")
    print(f"Área total: {total_area:.2f}")


def demo_herencia():
    """
    Demostración de relaciones de herencia.
    """
    print("\n=== Demostración de Herencia ===\n")

    # Crear instancias
    rectangulo = Rectangulo(Punto(0, 0), Punto(4, 3))
    cuadrado = Cuadrado(Punto(0, 0), 4)
    elipse = Elipse(Punto(0, 0), 3, 2)
    circulo = Circulo(Punto(0, 0), 3)

    print("Relaciones de herencia:")
    print(f"¿Cuadrado es instancia de Rectángulo? " f"{isinstance(cuadrado, Rectangulo)}")
    print(f"¿Círculo es instancia de Elipse? " f"{isinstance(circulo, Elipse)}")
    print(f"¿Rectángulo es instancia de Cuadrado? " f"{isinstance(rectangulo, Cuadrado)}")
    print()

    # Mostrar jerarquías de clases
    print("Jerarquías de clases:")
    print(f"Cuadrado MRO: " f"{[cls.__name__ for cls in Cuadrado.__mro__]}")
    print(f"Círculo MRO: " f"{[cls.__name__ for cls in Circulo.__mro__]}")


def demo_casos_especiales():
    """
    Demostración de casos especiales y validaciones.
    """
    print("\n=== Casos Especiales ===\n")

    # Figuras con valores por defecto
    print("Figuras con valores por defecto:")
    figuras_default = [Rectangulo(), Cuadrado(), Circulo(), Elipse(), Triangulo()]

    for figura in figuras_default:
        print(f"{figura} -> Área: {figura.area():.2f}")

    print()

    # Casos límite
    print("Casos límite:")

    # Triángulo degenerado (área = 0)
    triangulo_degenerado = Triangulo(Punto(0, 0), Punto(1, 0), Punto(2, 0))
    print(f"Triángulo degenerado: {triangulo_degenerado}")
    print(f"Área: {triangulo_degenerado.area():.2f}")

    # Círculo muy pequeño
    circulo_pequeno = Circulo(Punto(0, 0), 0.001)
    print(f"Círculo pequeño: {circulo_pequeno}")
    print(f"Área: {circulo_pequeno.area():.6f}")


if __name__ == "__main__":
    demo_polimorfismo()
    demo_herencia()
    demo_casos_especiales()

Program 1:Programación Orientada a Objetos - Figuras Geométricas

Output
=== Demostración de Polimorfismo con Figuras ===

--- Figura 1 ---
Figura: Rectangulo((0.0, 0.0), (3.0, 4.0))
  Perímetro: 14.00
  Área: 12.00

--- Figura 2 ---
Figura: Cuadrado((1.0, 1.0), lado=5.0)
  Perímetro: 20.00
  Área: 25.00

--- Figura 3 ---
Figura: Circulo(centro=(2.0, 2.0), radio=3.0)
  Perímetro: 18.85
  Área: 28.27

--- Figura 4 ---
Figura: Elipse(centro=(0.0, 0.0), radio_a=4.0, radio_b=2.0)
  Perímetro: 19.38
  Área: 25.13

--- Figura 5 ---
Figura: Triangulo((0.0, 0.0), (3.0, 0.0), (0.0, 4.0))
  Perímetro: 12.00
  Área: 6.00

--- Figura 6 ---
Figura: Triangulo((0.0, 0.0), (2.0, 0.0), (1.0, 1.732))
  Perímetro: 6.00
  Área: 1.73

==================================================
Total de figuras: 6
Perímetro total: 90.23
Área total: 98.14

=== Demostración de Herencia ===

Relaciones de herencia:
¿Cuadrado es instancia de Rectángulo? True
¿Círculo es instancia de Elipse? True
¿Rectángulo es instancia de Cuadrado? False

Jerarquías de clases:
Cuadrado MRO: ['Cuadrado', 'Rectangulo', 'object']
Círculo MRO: ['Circulo', 'Elipse', 'object']

=== Casos Especiales ===

Figuras con valores por defecto:
Rectangulo((0.0, 0.0), (1.0, 1.0)) -> Área: 1.00
Cuadrado((0.0, 0.0), lado=1.0) -> Área: 1.00
Circulo(centro=(0.0, 0.0), radio=1.0) -> Área: 3.14
Elipse(centro=(0.0, 0.0), radio_a=1.0, radio_b=1.0) -> Área: 3.14
Triangulo((0.0, 0.0), (1.0, 0.0), (0.0, 1.0)) -> Área: 0.50

Casos límite:
Triángulo degenerado: Triangulo((0.0, 0.0), (1.0, 0.0), (2.0, 0.0))
Área: 0.00
Círculo pequeño: Circulo(centro=(0.0, 0.0), radio=0.001)
Área: 0.000003

Descargar código completo de Figuras Geométricas

5Jerarquías de clases

El siguiente fragmento de código muestra la jerarquía de clases en Python:

import builtins


def print_class_tree(cls, prefix="", is_last=True, current_depth=0, max_depth=4):
    """
    Imprime el árbol de herencia de clases.

    :param cls: La clase raíz desde donde empezar.
    :param prefix: Prefijo para el formato visual (usado en recursión).
    :param is_last: Si es el último nodo de su rama (usado en recursión).
    :param current_depth: Profundidad actual (usado en recursión).
    :param max_depth: Nivel máximo de profundidad a mostrar.
    """

    # Si superamos la profundidad máxima, paramos esta rama
    if current_depth > max_depth:
        return

    # Imprimir el nodo actual
    if current_depth == 0:
        print(cls.__name__)
        new_prefix = ""
    else:
        connector = "└── " if is_last else "├── "
        print(f"{prefix}{connector}{cls.__name__}")
        new_prefix = prefix + ("    " if is_last else "│   ")

    # Obtener subclases directas
    try:
        subclasses = cls.__subclasses__()
    except TypeError:
        return

    # Filtrar solo clases del módulo 'builtins' (nativas de Python)
    # Esto elimina clases de librerías externas que ensucian el árbol.
    subclasses = [s for s in subclasses if s.__module__ == "builtins"]

    # Ordenar alfabéticamente para que la salida sea predecible
    subclasses.sort(key=lambda x: x.__name__)

    # Llamada recursiva para los hijos
    count = len(subclasses)
    for i, sub in enumerate(subclasses):
        is_last_sub = i == count - 1
        print_class_tree(sub, new_prefix, is_last_sub, current_depth + 1, max_depth)


# --- Ejecución ---
if __name__ == "__main__":
    # max_depth=4 muestra hasta Exception -> ArithmeticError -> ZeroDivisionError
    print_class_tree(object, max_depth=4)
Output
object
├── BaseException
│   ├── BaseExceptionGroup
│   │   └── ExceptionGroup
│   ├── Exception
│   │   ├── ArithmeticError
│   │   │   ├── FloatingPointError
│   │   │   ├── OverflowError
│   │   │   └── ZeroDivisionError
│   │   ├── AssertionError
│   │   ├── AttributeError
│   │   ├── BufferError
│   │   ├── EOFError
│   │   ├── ExceptionGroup
│   │   ├── ImportError
│   │   │   └── ModuleNotFoundError
│   │   ├── LookupError
│   │   │   ├── IndexError
│   │   │   └── KeyError
│   │   ├── MemoryError
│   │   ├── NameError
│   │   │   └── UnboundLocalError
│   │   ├── OSError
│   │   │   ├── BlockingIOError
│   │   │   ├── ChildProcessError
│   │   │   ├── ConnectionError
│   │   │   ├── FileExistsError
│   │   │   ├── FileNotFoundError
│   │   │   ├── InterruptedError
│   │   │   ├── IsADirectoryError
│   │   │   ├── NotADirectoryError
│   │   │   ├── PermissionError
│   │   │   ├── ProcessLookupError
│   │   │   └── TimeoutError
│   │   ├── ReferenceError
│   │   ├── RuntimeError
│   │   │   ├── NotImplementedError
│   │   │   ├── PythonFinalizationError
│   │   │   └── RecursionError
│   │   ├── StopAsyncIteration
│   │   ├── StopIteration
│   │   ├── SyntaxError
│   │   │   ├── IndentationError
│   │   │   └── _IncompleteInputError
│   │   ├── SystemError
│   │   ├── TypeError
│   │   ├── ValueError
│   │   │   └── UnicodeError
│   │   └── Warning
│   │       ├── BytesWarning
│   │       ├── DeprecationWarning
│   │       ├── EncodingWarning
│   │       ├── FutureWarning
│   │       ├── ImportWarning
│   │       ├── PendingDeprecationWarning
│   │       ├── ResourceWarning
│   │       ├── RuntimeWarning
│   │       ├── SyntaxWarning
│   │       ├── UnicodeWarning
│   │       └── UserWarning
│   ├── GeneratorExit
│   ├── KeyboardInterrupt
│   └── SystemExit
├── EncodingMap
├── FrameLocalsProxy
├── InstructionSequence
├── NoDefaultType
├── NoneType
├── NotImplementedType
├── PyCapsule
├── _buffer_wrapper
├── anext_awaitable
├── async_generator
├── async_generator_asend
├── async_generator_athrow
├── async_generator_wrapped_value
├── builtin_function_or_method
│   └── builtin_method
├── bytearray
├── bytearray_iterator
├── bytes
├── bytes_iterator
├── callable_iterator
├── cell
├── classmethod
├── classmethod_descriptor
├── code
├── complex
├── coroutine
├── coroutine_wrapper
├── dict
├── dict_itemiterator
├── dict_items
│   └── odict_items
├── dict_keyiterator
├── dict_keys
│   └── odict_keys
├── dict_reverseitemiterator
├── dict_reversekeyiterator
├── dict_reversevalueiterator
├── dict_valueiterator
├── dict_values
│   └── odict_values
├── ellipsis
├── enumerate
├── fieldnameiterator
├── filter
├── float
├── formatteriterator
├── frame
├── frozenset
├── function
├── generator
├── generic_alias_iterator
├── getset_descriptor
├── hamt
├── hamt_array_node
├── hamt_bitmap_node
├── hamt_collision_node
├── instancemethod
├── int
│   └── bool
├── items
├── iterator
├── keys
├── line_iterator
├── list
├── list_iterator
├── list_reverseiterator
├── longrange_iterator
├── managedbuffer
├── map
├── mappingproxy
├── member_descriptor
├── memory_iterator
├── memoryview
├── method
├── method-wrapper
├── method_descriptor
├── module
├── moduledef
├── odict_iterator
├── positions_iterator
├── property
├── range
├── range_iterator
├── reversed
├── set
├── set_iterator
├── slice
├── staticmethod
├── stderrprinter
├── str
├── str_ascii_iterator
├── str_iterator
├── super
├── symtable entry
├── traceback
├── tuple
│   ├── UnraisableHookArgs
│   └── asyncgen_hooks
├── tuple_iterator
├── type
├── values
├── wrapper_descriptor
└── zip

6Recursos para profundizar