Introduccion a tipos de objetos de python
Estimated learning time: 41 minutes
Introducción a Tipos de Objetos de Python
Todo programa Python trabaja con datos. Números, texto, listas de cosas, tablas de información — todo eso son datos. Y Python tiene formas muy bien diseñadas de representarlos. En este artículo conocerás los tipos de datos fundamentales que vienen incluidos en Python desde el primer día.
¿Por qué usar los tipos integrados de Python?
Antes de ver cada tipo, vale la pena entender por qué Python ya trae los suyos y por qué deberías usarlos en lugar de crear los tuyos propios desde cero.
Los tipos de datos principales de Python
Números
Los números son el tipo más básico. Python maneja tres variedades principales:
# Enteros (int) — sin decimales, tamaño ilimitado
edad = 25
poblacion_mundial = 8_100_000_000 # los _ ayudan a leer grandes números
negativo = -42
# Decimales (float) — con punto decimal
precio = 19.99
pi = 3.14159265
temperatura = -5.5
# Complejos (complex) — con parte imaginaria
z = 2 + 3j
Operaciones matemáticas
# Aritméticas básicas
print(10 + 3) # 13 — suma
print(10 - 3) # 7 — resta
print(10 * 3) # 30 — multiplicación
print(10 / 3) # 3.3333... — división (siempre da float)
print(10 // 3) # 3 — división entera (piso)
print(10 % 3) # 1 — módulo (resto de la división)
print(10 ** 3) # 1000 — potencia (10 elevado a 3)
# Funciones matemáticas del módulo math
import math
print(math.sqrt(16)) # 4.0 — raíz cuadrada
print(math.ceil(3.2)) # 4 — redondear arriba
print(math.floor(3.8)) # 3 — redondear abajo
print(abs(-7)) # 7 — valor absoluto
print(round(3.7)) # 4 — redondear normal
Números en detalle
# Los enteros en Python no tienen límite de tamaño
factorial_grande = 1
for i in range(1, 101):
factorial_grande *= i
print(factorial_grande) # ¡Python maneja números enormes sin problema!
# Conversión entre tipos
print(int(3.9)) # 3 — float a int (trunca, no redondea)
print(float(5)) # 5.0 — int a float
print(str(42)) # "42" — número a texto
# Comparaciones (devuelven True o False)
print(10 > 5) # True
print(10 == 10) # True
print(10 != 5) # True
print(3 >= 3) # True
Cadenas de texto (Strings)
Una cadena es una secuencia de caracteres. Es el tipo que usas para representar texto.
# Distintas formas de crear cadenas
saludo = "Hola, mundo" # comillas dobles
nombre = 'Python' # comillas simples (equivalente)
parrafo = """Este texto
ocupa varias
líneas""" # triple comilla para múltiples líneas
con_escape = "Línea 1\nLínea 2" # \n = salto de línea
Operaciones de secuencia
Las cadenas son secuencias — esto significa que puedes acceder a cada carácter por su posición (índice) y extraer partes con slicing.
s = "Python"
# Indexing — acceder a un carácter por posición
print(s[0]) # "P" — primer carácter
print(s[1]) # "y"
print(s[-1]) # "n" — último carácter
print(s[-2]) # "o" — penúltimo
# Slicing — extraer una porción [inicio:fin:paso]
print(s[0:3]) # "Pyt" — desde índice 0 hasta 2 (el 3 no se incluye)
print(s[2:]) # "thon" — desde índice 2 hasta el final
print(s[:3]) # "Pyt" — desde el inicio hasta índice 2
print(s[:]) # "Python" — copia completa
print(s[::2]) # "Pto" — cada 2 caracteres (paso)
print(s[::-1]) # "nohtyP" — invertir la cadena
# Longitud
print(len(s)) # 6
# Concatenación y repetición
print(s + " 3.12") # "Python 3.12"
print(s * 3) # "PythonPythonPython"
# Pertenencia
print("y" in s) # True
print("z" in s) # False
Inmutabilidad
🔴 Concepto importante: Las cadenas son inmutables — no puedes cambiar un carácter individual una vez creada la cadena. Si necesitas modificarla, debes crear una nueva.
s = "Python"
# Esto lanza un error:
# s[0] = "J" ← TypeError: 'str' object does not support item assignment
# La forma correcta: crear una nueva cadena
s = "J" + s[1:]
print(s) # "Jython"
Métodos específicos de cadenas
Los métodos son funciones incorporadas en cada tipo de dato. Se llaman con .nombre_metodo().
s = " Hola, Mundo Python "
# Mayúsculas y minúsculas
print(s.upper()) # " HOLA, MUNDO PYTHON "
print(s.lower()) # " hola, mundo python "
print(s.capitalize()) # " hola, mundo python " → solo primera mayúscula
print(s.title()) # " Hola, Mundo Python " → cada palabra en mayúscula
# Limpieza de espacios
print(s.strip()) # "Hola, Mundo Python" — elimina espacios a ambos lados
print(s.lstrip()) # "Hola, Mundo Python " — solo lado izquierdo
print(s.rstrip()) # " Hola, Mundo Python" — solo lado derecho
# Búsqueda y reemplazo
print(s.find("Mundo")) # 8 — posición donde empieza (o -1 si no existe)
print(s.replace("Mundo", "Universo")) # " Hola, Universo Python "
print(s.count("o")) # 3 — cuántas veces aparece
# División y unión
palabras = "uno,dos,tres".split(",") # ["uno", "dos", "tres"]
print(palabras)
unido = " - ".join(palabras) # "uno - dos - tres"
print(unido)
# Verificaciones (devuelven True/False)
print("123".isdigit()) # True — ¿solo dígitos?
print("abc".isalpha()) # True — ¿solo letras?
print(" ".isspace()) # True — ¿solo espacios?
print("hola".startswith("ho")) # True
print("hola".endswith("la")) # True
Cómo obtener ayuda sobre métodos
# Ver todos los métodos disponibles de un tipo
print(dir("cualquier cadena"))
# Ver la documentación de un método específico
help(str.replace)
# o en el intérprete interactivo:
# >>> help("hola".replace)
Otras formas de escribir cadenas
# Cadenas f (f-strings) — la forma moderna de insertar variables
nombre = "Ana"
edad = 28
print(f"Me llamo {nombre} y tengo {edad} años")
# "Me llamo Ana y tengo 28 años"
# Expresiones dentro de f-strings
print(f"El doble de {edad} es {edad * 2}")
# "El doble de 28 es 56"
# Formato con .format() — estilo anterior
print("Me llamo {} y tengo {} años".format(nombre, edad))
# Formato con % — estilo más antiguo (aún válido)
print("Me llamo %s y tengo %d años" % (nombre, edad))
# Cadenas raw (r-strings) — ignoran las barras invertidas
ruta_windows = r"C:\Users\Ana\Documents" # sin r, \U y \D causarían problemas
print(ruta_windows) # C:\Users\Ana\Documents
# Cadenas de bytes
datos = b"Hola en bytes"
print(type(datos)) # <class 'bytes'>
Coincidencia de patrones (Pattern Matching)
Para búsquedas avanzadas en texto, Python tiene el módulo re (expresiones regulares):
import re
texto = "Mi email es ana@ejemplo.com y también uso ana2@trabajo.org"
# Buscar un patrón
patron = r"[\w.]+@[\w.]+\.\w+" # patrón de email
emails = re.findall(patron, texto)
print(emails) # ['ana@ejemplo.com', 'ana2@trabajo.org']
# Verificar si un texto coincide con un patrón
if re.match(r"\d{4}-\d{2}-\d{2}", "2024-03-15"):
print("Formato de fecha válido")
# Reemplazar con patrón
resultado = re.sub(r"\d+", "#", "Tengo 3 gatos y 2 perros")
print(resultado) # "Tengo # gatos y # perros"
Listas
Las listas son colecciones ordenadas que pueden contener cualquier tipo de dato — y pueden mezclarlos.
# Crear listas
vacia = []
numeros = [1, 2, 3, 4, 5]
textos = ["manzana", "pera", "uva"]
mezclada = [42, "hola", True, 3.14, None]
lista_larga = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Operaciones de secuencia
Al igual que las cadenas, las listas son secuencias y comparten operaciones similares:
frutas = ["manzana", "pera", "uva", "kiwi"]
# Indexing y slicing
print(frutas[0]) # "manzana"
print(frutas[-1]) # "kiwi"
print(frutas[1:3]) # ["pera", "uva"]
print(frutas[::-1]) # ["kiwi", "uva", "pera", "manzana"] — invertida
# Longitud, concatenación, pertenencia
print(len(frutas)) # 4
print(frutas + ["melón"]) # ["manzana", "pera", "uva", "kiwi", "melón"]
print("pera" in frutas) # True
print("mango" in frutas) # False
Operaciones específicas de listas
A diferencia de las cadenas, las listas son mutables — puedes modificarlas directamente:
frutas = ["manzana", "pera", "uva"]
# Modificar un elemento
frutas[0] = "melón"
print(frutas) # ["melón", "pera", "uva"]
# Agregar elementos
frutas.append("kiwi") # agrega al final
frutas.insert(1, "naranja") # inserta en posición 1
print(frutas) # ["melón", "naranja", "pera", "uva", "kiwi"]
# Eliminar elementos
frutas.remove("pera") # elimina por valor
del frutas[0] # elimina por índice
ultimo = frutas.pop() # extrae y devuelve el último elemento
print(frutas)
# Ordenar
numeros = [3, 1, 4, 1, 5, 9, 2, 6]
numeros.sort() # ordena la lista en su lugar
print(numeros) # [1, 1, 2, 3, 4, 5, 6, 9]
numeros_ordenados = sorted([3,1,4]) # devuelve nueva lista sin modificar la original
# Otros métodos
print(numeros.count(1)) # 2 — cuántas veces aparece el 1
print(numeros.index(5)) # 4 — posición del 5
numeros.reverse() # invierte en su lugar
Control de límites (Bounds Checking)
⚠️ Si intentas acceder a un índice que no existe, Python lanza un
IndexError:
lista = [10, 20, 30]
print(lista[0]) # 10 ✅
print(lista[2]) # 30 ✅
print(lista[3]) # ❌ IndexError: list index out of range
# Cómo evitarlo: verificar antes
indice = 5
if indice < len(lista):
print(lista[indice])
else:
print("Índice fuera de rango")
Anidamiento (Nesting)
Las listas pueden contener otras listas — esto permite representar estructuras como tablas o matrices:
# Matriz 3x3
matriz = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Acceder a un elemento: fila primero, columna después
print(matriz[0][0]) # 1 — fila 0, columna 0
print(matriz[1][2]) # 6 — fila 1, columna 2
print(matriz[2][1]) # 8 — fila 2, columna 1
# Listas anidadas con diferentes tipos
datos_persona = ["Ana", 28, ["Python", "JavaScript", "SQL"]]
print(datos_persona[0]) # "Ana"
print(datos_persona[2][0]) # "Python"
Comprensiones de listas (Comprehensions)
Las comprensiones son una forma elegante y concisa de crear listas a partir de otras:
# Forma tradicional (con bucle)
cuadrados = []
for n in range(1, 6):
cuadrados.append(n ** 2)
print(cuadrados) # [1, 4, 9, 16, 25]
# Con comprensión de lista — mismo resultado, una sola línea
cuadrados = [n ** 2 for n in range(1, 6)]
print(cuadrados) # [1, 4, 9, 16, 25]
# Con filtro (condición)
pares = [n for n in range(10) if n % 2 == 0]
print(pares) # [0, 2, 4, 6, 8]
# Con transformación de texto
frutas = ["manzana", "pera", "uva"]
mayusculas = [f.upper() for f in frutas]
print(mayusculas) # ["MANZANA", "PERA", "UVA"]
# Anidadas — equivale a dos bucles
pares_xy = [(x, y) for x in range(3) for y in range(3)]
print(pares_xy)
# [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)]
Diccionarios
Los diccionarios almacenan pares clave: valor. En lugar de acceder por posición numérica, accedes por nombre (clave).
Piénsalos como un diccionario real: buscas una palabra (clave) y obtienes su definición (valor).
# Crear diccionarios
vacio = {}
persona = {"nombre": "Ana", "edad": 28, "ciudad": "Madrid"}
precios = {"manzana": 1.2, "pera": 0.8, "uva": 2.5}
mezclado = {"id": 1, "activo": True, "tags": ["python", "dev"]}
Operaciones de mapeo
persona = {"nombre": "Ana", "edad": 28, "ciudad": "Madrid"}
# Acceder a un valor por clave
print(persona["nombre"]) # "Ana"
print(persona["edad"]) # 28
# Modificar un valor
persona["edad"] = 29
print(persona["edad"]) # 29
# Agregar una nueva clave
persona["email"] = "ana@email.com"
# Eliminar una clave
del persona["ciudad"]
# Verificar si una clave existe
print("nombre" in persona) # True
print("ciudad" in persona) # False
# Obtener todas las claves, valores o pares
print(persona.keys()) # dict_keys(["nombre", "edad", "email"])
print(persona.values()) # dict_values(["Ana", 29, "ana@email.com"])
print(persona.items()) # dict_items([("nombre","Ana"), ("edad",29), ...])
Anidamiento revisitado
Los diccionarios pueden contener otros diccionarios, listas, o cualquier combinación:
# Estructura anidada — datos de una empresa
empresa = {
"nombre": "TechCorp",
"empleados": [
{"nombre": "Ana", "rol": "desarrolladora", "skills": ["Python", "SQL"]},
{"nombre": "Carlos","rol": "diseñador", "skills": ["Figma", "CSS"]},
],
"sede": {
"ciudad": "Madrid",
"pais": "España",
"codigo_postal": "28001"
}
}
# Acceder a datos anidados
print(empresa["nombre"]) # "TechCorp"
print(empresa["empleados"][0]["nombre"]) # "Ana"
print(empresa["empleados"][0]["skills"][1]) # "SQL"
print(empresa["sede"]["ciudad"]) # "Madrid"
Ordenar claves: bucles for
Los diccionarios se recorren con for. Para ordenar las claves al iterar:
precios = {"uva": 2.5, "manzana": 1.2, "pera": 0.8, "kiwi": 1.8}
# Iterar sobre claves (orden de inserción desde Python 3.7+)
for fruta in precios:
print(f"{fruta}: {precios[fruta]}€")
# Iterar ordenado alfabéticamente
for fruta in sorted(precios):
print(f"{fruta}: {precios[fruta]}€")
# Iterar sobre pares clave-valor
for fruta, precio in precios.items():
print(f"{fruta} cuesta {precio}€")
# Iterar ordenado por valor (de menor a mayor precio)
for fruta in sorted(precios, key=lambda f: precios[f]):
print(f"{fruta}: {precios[f]}€")
Claves faltantes: sentencias if
Si intentas acceder a una clave que no existe, Python lanza un KeyError. Hay varias formas de manejarlo:
persona = {"nombre": "Ana", "edad": 28}
# ❌ Esto lanza KeyError:
# print(persona["email"])
# ✅ Forma 1: verificar con in antes de acceder
if "email" in persona:
print(persona["email"])
else:
print("No tiene email registrado")
# ✅ Forma 2: usar .get() con valor por defecto
email = persona.get("email", "sin email")
print(email) # "sin email"
# ✅ Forma 3: setdefault — obtiene o crea con valor por defecto
visitas = {}
visitas.setdefault("Ana", 0)
visitas["Ana"] += 1
print(visitas) # {"Ana": 1}
# ✅ Forma 4: defaultdict del módulo collections
from collections import defaultdict
contador = defaultdict(int) # valor por defecto: 0
contador["manzana"] += 1
contador["pera"] += 3
print(dict(contador)) # {"manzana": 1, "pera": 3}
Tuplas
Las tuplas son como las listas — colecciones ordenadas — pero inmutables: una vez creadas no pueden modificarse.
# Crear tuplas
vacia = ()
un_elemento = (42,) # ← la coma es obligatoria para tuplas de 1 elemento
coordenadas = (10.5, 20.3)
rgb = (255, 128, 0)
mezclada = ("Ana", 28, True)
# También se pueden crear sin paréntesis (Python los infiere)
punto = 3, 4
print(type(punto)) # <class 'tuple'>
# Acceso igual que listas
print(coordenadas[0]) # 10.5
print(rgb[-1]) # 0
print(rgb[0:2]) # (255, 128)
¿Por qué usar tuplas?
# Usos típicos de tuplas
# 1. Retornar múltiples valores de una función
def minmax(lista):
return min(lista), max(lista) # retorna una tupla
minimo, maximo = minmax([3, 1, 4, 1, 5, 9])
print(minimo, maximo) # 1 9
# 2. Desempaquetado (unpacking)
coordenadas = (10.5, 20.3, 5.0)
x, y, z = coordenadas
print(x) # 10.5
# 3. Como claves de diccionario (las listas no pueden ser claves)
ubicaciones = {}
ubicaciones[(40.4, -3.7)] = "Madrid"
ubicaciones[(41.4, 2.2)] = "Barcelona"
# 4. Datos que no deben modificarse
DIAS_SEMANA = ("lunes", "martes", "miércoles", "jueves", "viernes", "sábado", "domingo")
Archivos
Los archivos permiten leer y escribir datos de forma persistente — es decir, que se guardan aunque cierres el programa.
# ESCRIBIR en un archivo
with open("datos.txt", "w") as archivo:
archivo.write("Primera línea\n")
archivo.write("Segunda línea\n")
archivo.writelines(["Tercera\n", "Cuarta\n"])
# LEER un archivo completo
with open("datos.txt", "r") as archivo:
contenido = archivo.read()
print(contenido)
# LEER línea por línea (eficiente para archivos grandes)
with open("datos.txt", "r") as archivo:
for linea in archivo:
print(linea.strip()) # .strip() elimina el \n al final
# AÑADIR al final sin borrar lo existente
with open("datos.txt", "a") as archivo:
archivo.write("Quinta línea\n")
💡 El bloque
withgarantiza que el archivo se cierre correctamente aunque ocurra un error. Siempre úsalo.
Modos de apertura de archivos
| Modo | Significado |
|---|---|
"r" | Solo lectura (error si no existe) |
"w" | Escritura (crea o sobreescribe) |
"a" | Añadir al final |
"r+" | Lectura y escritura |
"rb" | Lectura en modo binario |
"wb" | Escritura en modo binario |
Otras herramientas similares a archivos
# StringIO — archivo en memoria (útil para tests)
from io import StringIO
archivo_virtual = StringIO("línea 1\nlínea 2\n")
print(archivo_virtual.read())
# Archivos JSON — formato muy común para intercambiar datos
import json
datos = {"nombre": "Ana", "edad": 28, "skills": ["Python", "SQL"]}
# Escribir JSON
with open("datos.json", "w") as f:
json.dump(datos, f, indent=2)
# Leer JSON
with open("datos.json", "r") as f:
cargado = json.load(f)
print(cargado["nombre"]) # "Ana"
# Archivos CSV
import csv
with open("personas.csv", "w", newline="") as f:
escritor = csv.writer(f)
escritor.writerow(["nombre", "edad"])
escritor.writerow(["Ana", 28])
escritor.writerow(["Carlos", 35])
Otros tipos principales
Conjuntos (Sets)
Un conjunto es una colección sin duplicados y sin orden. Útil para eliminar repetidos y operaciones matemáticas de conjuntos.
# Crear conjuntos
colores = {"rojo", "verde", "azul"}
numeros = {1, 2, 3, 2, 1, 3} # los duplicados se eliminan
print(numeros) # {1, 2, 3}
# Eliminar duplicados de una lista
lista_con_repetidos = [1, 2, 2, 3, 3, 3, 4]
sin_repetidos = list(set(lista_con_repetidos))
print(sin_repetidos) # [1, 2, 3, 4]
# Operaciones de conjuntos
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b) # {1,2,3,4,5,6} — unión
print(a & b) # {3,4} — intersección
print(a - b) # {1,2} — diferencia
print(a ^ b) # {1,2,5,6} — diferencia simétrica
Booleanos
# Solo dos valores posibles
verdadero = True
falso = False
# Son el resultado de comparaciones
print(5 > 3) # True
print(5 == 3) # False
# Operadores lógicos
print(True and False) # False
print(True or False) # True
print(not True) # False
# En Python, True y False son internamente 1 y 0
print(True + True) # 2
print(True * 5) # 5
None
None representa la ausencia de valor — como decir "aquí no hay nada".
resultado = None
# Verificar si algo es None
if resultado is None:
print("Aún no hay resultado")
# Función que no retorna nada explícitamente devuelve None
def saludar(nombre):
print(f"Hola {nombre}")
retorno = saludar("Ana") # imprime "Hola Ana"
print(retorno) # None
Cómo romper la flexibilidad de tu código
Python es muy flexible, pero esa flexibilidad puede generar bugs si no tienes cuidado. Aquí los errores más comunes:
# ❌ Mezclar tipos sin querer
precio = "10" # string, no número
total = precio * 3
print(total) # "101010" — ¡concatena 3 veces en vez de multiplicar!
# ✅ Solución: convertir al tipo correcto
precio = int("10")
total = precio * 3
print(total) # 30 ✅
# ❌ Modificar una lista mientras la recorres
numeros = [1, 2, 3, 4, 5]
for n in numeros:
if n % 2 == 0:
numeros.remove(n) # ¡Bug! se saltan elementos
print(numeros) # [1, 3, 5] — parece bien, pero con otros datos falla
# ✅ Solución: usar comprensión de lista
numeros = [1, 2, 3, 4, 5]
impares = [n for n in numeros if n % 2 != 0]
print(impares) # [1, 3, 5] ✅
# ❌ Comparar con == en lugar de is para None
resultado = None
if resultado == None: # funciona, pero no es la forma correcta
pass
# ✅ Solución
if resultado is None: # la forma pythónica
pass
Clases definidas por el usuario
Python permite crear tus propios tipos combinando datos y comportamiento en una clase. Esto es Programación Orientada a Objetos (POO).
# Definir una clase — un nuevo tipo de dato propio
class Persona:
def __init__(self, nombre, edad): # constructor
self.nombre = nombre
self.edad = edad
def saludar(self):
print(f"Hola, soy {self.nombre} y tengo {self.edad} años")
def cumpleaños(self):
self.edad += 1
print(f"¡Feliz cumpleaños {self.nombre}! Ahora tienes {self.edad}")
# Crear instancias (objetos) de la clase
ana = Persona("Ana", 28)
carlos = Persona("Carlos", 35)
# Usar los métodos
ana.saludar() # "Hola, soy Ana y tengo 28 años"
carlos.saludar() # "Hola, soy Carlos y tengo 35 años"
ana.cumpleaños() # "¡Feliz cumpleaños Ana! Ahora tienes 29"
# El tipo es la clase
print(type(ana)) # <class '__main__.Persona'>
💡 Las clases son el tema central de la Programación Orientada a Objetos. Las veremos en profundidad en un artículo dedicado. Por ahora, lo importante es saber que puedes crear tus propios tipos que se comportan igual que los tipos integrados.
Y todo lo demás
Python tiene muchos más tipos y herramientas avanzadas que irás descubriendo:
# Rangos — secuencias numéricas perezosas (no ocupan memoria)
r = range(0, 100, 2) # números pares del 0 al 98
print(list(r[:5])) # [0, 2, 4, 6, 8]
# Generadores — como comprensiones pero más eficientes en memoria
cuadrados = (n**2 for n in range(1000000)) # no crea la lista completa
print(next(cuadrados)) # 0
print(next(cuadrados)) # 1
# Enumerados con enum
from enum import Enum
class Color(Enum):
ROJO = 1
VERDE = 2
AZUL = 3
print(Color.ROJO) # Color.ROJO
print(Color.ROJO.value) # 1
# Tipos con anotaciones (Type Hints) — Python 3.5+
def suma(a: int, b: int) -> int:
return a + b
# No son obligatorias, pero ayudan al editor a detectar errores
Resumen visual del capítulo
Preguntas frecuentes
¿Cuándo uso una lista y cuándo una tupla? Usa lista cuando necesitas agregar, quitar o modificar elementos. Usa tupla cuando los datos no deben cambiar (coordenadas, configuración, constantes).
¿Cuándo uso una lista y cuándo un diccionario? Usa lista para colecciones donde el orden importa y accedes por posición. Usa diccionario cuando necesitas buscar datos por nombre o etiqueta.
¿Por qué las cadenas son inmutables? Por eficiencia y seguridad. Python puede reutilizar el mismo objeto en memoria para cadenas iguales (interning), lo que ahorra memoria. Y garantiza que una función no pueda modificar la cadena que le pasas.
¿Qué es un método y cómo sé cuáles tiene un tipo?
Un método es una función propia de un tipo. Para ver todos los métodos disponibles escribe dir(objeto) en el intérprete, o help(tipo) para documentación detallada.
¿Puedo crear mis propios tipos como int o str?
Sí, usando clases. Tus clases pueden comportarse igual que los tipos integrados si implementas los métodos especiales adecuados (como __len__, __add__, etc.).
Con los tipos de datos bien dominados, el siguiente paso es aprender a controlar el flujo de tu programa: condicionales if, bucles for y while, y funciones.
