Skip to content
This page has been auto-translated and may contain errors.View in English

Salida y entrada

docs.scrimba.com

Dos herramientas que usarás desde la primera línea que escribas: print() muestra valores en la terminal, input() obtiene texto del usuario. Son simples, pero saber cómo se comportan te ahorra sorpresas al principio.

print() e input() son las funciones estándar de E/S de terminal de Python. Ambas son más configurables de lo que parecen. print() acepta argumentos que controlan cómo se unen los valores y dónde termina la salida. input() siempre devuelve una cadena, lo que afecta cómo manejas cada valor que proviene del usuario.

Bajo el capó, print() escribe en sys.stdout e input() lee de sys.stdin (los flujos estándar de salida y entrada a los que está conectada tu terminal). Ambas se ocupan solo de texto, y la salida está almacenada en búfer de forma predeterminada: Python la mantiene brevemente y escribe en fragmentos en lugar de un carácter a la vez. Dos consecuencias importan en programas reales: la salida va a un flujo diferente del de los errores (stdout versus stderr), y puedes forzar el vaciado de ese búfer cuando necesites que la salida aparezca inmediatamente.

Cómo Python ejecuta tu código

Python ejecuta tu código de arriba a abajo, una línea a la vez, exactamente en el orden en que la escribiste. Sin saltos. El orden en que escribes las cosas es el orden en que se ejecutan. Siempre.

python
city = "Ciudad de México"
print(city)
print("Población: 9 millones")

city se asigna primero. Se ejecuta el primer print. Se ejecuta el segundo print. Cada vez, en ese orden.

Esto importa porque no puedes usar una variable antes de haberla asignado. Python aún no la ha visto y lanzará un error:

python
print(country)   # NameError: country aún no está definido
country = "México"

Ten esto en mente mientras tus programas crecen: cualquier cosa que uses debe estar definida antes de usarla.

Python usa ejecución secuencial: cada sentencia se evalúa cuando se encuentra, en un solo paso de arriba a abajo a través del archivo. No hay un pre-escaneo de todo el archivo primero. Referenciar un nombre antes de asignarlo levanta NameError exactamente en esa línea, no antes.

python
city = "Ciudad de México"
print(city)             # funciona: city ya está vinculada
print(country)          # NameError: aún no asignada
country = "México"

La regla: las dependencias deben estar definidas antes de la línea que las usa.

Python ejecuta tu archivo en un solo paso de arriba a abajo, y solo busca un nombre en el momento en que esa línea realmente se ejecuta, no cuando primero lee el archivo. Por eso un nombre faltante es un NameError en tiempo de ejecución (cuando se ejecuta la línea) en lugar de un error instantáneamente cuando guardas. No hay hoisting (la forma en que JavaScript mueve silenciosamente las declaraciones de var al inicio de su alcance) y no hay declaraciones forward (la forma en que C te deja prometer un nombre ahora y definirlo después). Un nombre existe en el momento en que se asigna, y cualquier uso antes levanta un error.

python
print(country)   # NameError en tiempo de ejecución, no error de sintaxis
country = "México"
JunoCómo Python ejecuta tu código Python lee tu archivo de arriba a abajo, una línea a la vez, en el orden en que la escribiste. El problema que atrapa a todos una vez: un nombre tiene que existir antes de la línea que lo usa, o obtienes un NameError. Sin saltos, sin leer todo el archivo primero.
JunoCómo Python ejecuta tu código De arriba a abajo, un paso, en orden. Un nombre tiene que estar asignado antes de cualquier línea que lo use, de lo contrario es un NameError en esa línea exacta. Sin pre-escaneo del archivo.
JunoCómo Python ejecuta tu código Un paso de arriba a abajo, nombres buscados cuando cada línea se ejecuta. Usa un nombre antes de que esté asignado y obtienes un NameError en tiempo de ejecución, no error de sintaxis. Python no hace hoisting y no tiene declaraciones forward, así que el orden realmente lo es todo.

Imprimiendo salida

print() es cómo Python te habla de vuelta. Pásale cualquier valor y muestra ese valor. Convierte automáticamente lo que le das en texto.

print() convierte cada argumento a una cadena a través de str(), los une con un separador (un espacio de forma predeterminada), luego escribe el resultado seguido de una nueva línea en la salida estándar. Entender los valores predeterminados hace que los argumentos opcionales sean más predecibles.

La firma completa de print() es print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False). El colector *objects acepta cualquier número de argumentos posicionales y llama a str() en cada uno. sep y end controlan el formato; file redirige la salida a cualquier flujo escribible; flush fuerza el búfer a vaciarse inmediatamente.

python
print("Hello")    # Hello
print(42)         # 42
print(3.14)       # 3.14
print(True)       # True

Múltiples valores

Puedes imprimir múltiples valores a la vez separándolos con comas. Python pone un espacio entre ellos de forma predeterminada. Cambia el separador con sep:

Múltiples argumentos posicionales se convierten cada uno con str() individualmente, luego se unen con sep. El sep predeterminado es un espacio único. Sobrescribirlo te permite producir salida formateada sin concatenación de cadenas:

print() no construye una cadena y la escribe; escribe cada argumento en el flujo por turno (llamando a str() en cada uno), con sep entre y end al final. Porque esas escrituras suceden una a la vez en lugar de como una operación única bloqueada, dos llamadas print() ejecutándose al mismo tiempo (en diferentes hilos) pueden intercalar su salida. Cuando eso importa, construye una cadena e imprímela de una vez. Para uso cotidiano, sobrescribir sep aún vence a pegar cadenas juntas a mano:

python
name = "Carlos"
age = 28
print(name, age)                        # Carlos 28
print("Name:", name)                    # Name: Carlos
print("2024", "01", "15", sep="-")     # 2024-01-15
print("a", "b", "c", sep=", ")         # a, b, c

Controlando el final de la línea

Cada llamada print() termina con una nueva línea de forma predeterminada, así que la siguiente salida comienza en una línea nueva. Cambia eso con end. Establecer end="" hace que el siguiente print continúe en la misma línea:

El parámetro end reemplaza la nueva línea predeterminada. Establécelo en "" para suprimir el salto de línea, en " " para permanecer en la misma línea con un espacio, o a cualquier otra cadena. Combinado con sep, puedes producir la mayoría de los formatos de salida sin construir cadenas manualmente:

sep y end son solo nombrados por palabras clave (los pasas por nombre, como end="", nunca por posición), con valores predeterminados de un espacio y una nueva línea. end="" es la forma estándar de imprimir una línea parcial y dejar que la siguiente llamada la continúe. Para salida que necesita aparecer mientras sucede, como un indicador de progreso o un registro en vivo, añade flush=True para que Python escriba inmediatamente en lugar de esperar una nueva línea o a que su búfer se llene.

python
print("Loading", end="")
print("...")
# Loading...

print("one", end=" | ")
print("two", end=" | ")
print("three")
# one | two | three
JunoImprimiendo salidaprint() convierte lo que le des en texto y lo muestra. Pasa varias cosas separadas por comas y obtienes un espacio entre ellas, cambia eso con sep. Cada print baja a una línea nueva al final; end="" mantiene el siguiente en la misma línea.
JunoImprimiendo salidaprint() ejecuta str() en cada argumento, los une con sep (un espacio de forma predeterminada), y termina con end (una nueva línea de forma predeterminada). Sobrescribe cualquiera para formatear salida sin pegar cadenas juntas.
JunoImprimiendo salidaprint() escribe cada argumento a través de str(), con sep entre y end al final, ambos solo nombrados por palabras clave. Usa end="" para continuar una línea, y flush=True cuando la salida necesita aparecer ahora mismo.

Formateando salida con f-strings

La forma más limpia de construir mensajes es con f-strings. Pon f antes de la comilla de apertura, luego envuelve cualquier variable o expresión en llaves. Python la rellena en tiempo de ejecución. Puedes poner cualquier valor, cálculo, o llamada a método dentro de {}.

Los f-strings evalúan cualquier expresión dentro de {} en tiempo de ejecución e incrustan el resultado como una cadena. Un dos puntos después del valor introduce una especificación de formato: una sintaxis compacta para controlar lugares decimales, alineación, y formato de números. Son más rápidos y legibles que la concatenación, y no requieren llamadas explícitas a str().

Cada {} en un f-string termina llamando a format(value, spec), que pasa al método __format__ del valor (un dunder, el método de doble guión bajo que Python llama para formatear un valor). Así que cualquier clase puede decidir cómo se ve dentro de un f-string definiendo __format__. Las banderas de conversión !r, !s, y !a ejecutan repr(), str(), o ascii() en el valor primero; !r es la que recordar para depuración, porque muestra un valor de la forma en que la escribirías en código (comillas, escapes y todo), mostrado en práctica a continuación.

python
name = "Carlos"
score = 980

# concatenación: torpe, requiere str() para números
print("Player: " + name + ", Score: " + str(score))

# f-string: legible, sin conversión manual
print(f"Player: {name}, Score: {score}")

Puedes poner cualquier expresión dentro de {}: aritmética, llamadas a método (como .upper(), cubierto completamente en el capítulo Strings), especificaciones de formato:

python
price = 49.99
tax = 0.2
total = price * (1 + tax)

print(f"Total: {total:.2f}")          # Total: 59.99
print(f"Name: {name.upper()}")        # Name: CARLOS
print(f"2 + 2 = {2 + 2}")             # 2 + 2 = 4

La especificación de formato después de : controla cómo se muestra el valor:

python
ratio = 0.8765
count = 1234567
label = "revenue"

print(f"{ratio:.1%}")       # 87.6%
print(f"{count:,}")         # 1,234,567
print(f"{label:>12}")       # "     revenue"

:.2f significa "dos lugares decimales". Lo usarás constantemente para precios y medidas. Todo lo demás está ahí cuando lo necesites. Lo principal: cualquier cosa puede ir dentro de {}, no solo nombres de variables.

:.2f y :.0% cubren la mayoría de las necesidades de formato. Los especificadores de alineación (>, <, ^) con un ancho producen salida tabular ordenada. El patrón general es {value:[align][width][.precision][type]}. Una vez que reconoces las partes, cualquier especificación es legible sin memorizar todas las combinaciones.

La misma especificación puede significar cosas diferentes para tipos diferentes, porque cada tipo se formatea a sí mismo. f"{'hi':5}" rellena texto a la derecha (el texto se alinea a la izquierda de forma predeterminada) mientras que f"{42:5}" rellena a la izquierda (los números se alinean a la derecha): mismo :5, resultado opuesto. Cada tipo integrado lleva sus propias reglas para este mini-lenguaje de formato, y una clase personalizada establece la suya propia definiendo __format__.

JunoFormateando salida con f-strings Pon f antes de la comilla de apertura y envuelve cualquier cosa en {}: una variable, una suma, incluso una llamada a método. Un dos puntos añade formato, como :.2f para dos lugares decimales. Mucho más limpio que pegar cadenas juntas con +.
JunoFormateando salida con f-stringsf"..." coloca el resultado de cualquier expresión directamente en la cadena, sin str() necesaria. Después de un dos puntos viene la especificación de formato: :.2f, :,, :>12 y similares. Más limpio y rápido que la concatenación.
JunoFormateando salida con f-strings Cada {} llama a `__format__` del valor, así que la especificación después del dos puntos significa lo que ese tipo decide. !r es la que recordar: muestra un valor de la forma en que lo escribirías, lo que hace que espacios al final y otras cosas invisibles se destaquen cuando estás depurando.

Obteniendo entrada del usuario

input() pausa tu programa y espera a que el usuario escriba algo. Lo que sea que escriban (y presionen Enter) vuelve como el valor de retorno. La cadena entre paréntesis es el prompt que ve el usuario.

python
name = input("¿Cuál es tu nombre? ")
print(f"¡Hola, {name}!")

input() siempre devuelve una cadena, sin importar qué escriba el usuario. Escribe 42 y obtienes "42", no el número 42. Para hacer aritmética con ello, convierte explícitamente:

python
age = int(input("¿Cuántos años tienes? "))
print(f"En diez años tendrás {age + 10}.")

¿Y si el usuario escribe algo que no puede convertirse? Python lanza un ValueError. Manejar eso apropiadamente se cubre en el capítulo Files and exceptions.

input() escribe el prompt en la salida estándar, lee una línea de la entrada estándar, quita la nueva línea al final, y devuelve el resultado como una cadena. No hay inferencia de tipos. Todo desde la terminal llega como texto; declaras qué tipo necesitas convirtiendo explícitamente en el límite.

python
name = input("¿Cuál es tu nombre? ")
age = int(input("¿Cuántos años tienes? "))

Este patrón (recibir texto, convertir al tipo que necesitas) se aplica en todas partes donde llegan datos externos. int(), float(), y str() son las herramientas de conversión. Si la cadena no puede convertirse, Python lanza ValueError, cubierto en el capítulo Files and exceptions.

input() es un envoltorio delgado: escribe el prompt en sys.stdout (salida estándar), lo vacía para que el prompt aparezca antes de que el programa se bloquee, lee una línea de sys.stdin (entrada estándar), quita la nueva línea al final, y devuelve un str. Siempre es un str por diseño, porque Python no puede adivinar si "42" fue destinado como un entero, un flotante, o texto literal. Así que conviertes en el límite. Esta es la forma fundamental de E/S de Python: los datos externos llegan como texto, y tu código decide su tipo en el punto de entrada.

python
name = input("Ingresa tu nombre: ")
score = float(input("Ingresa tu puntuación (0.0 a 1.0): "))

print(f"Name:  {name!r}")      # !r revela cualquier espacio en blanco invisible
print(f"Score: {score:.1%}")
JunoObteniendo entrada del usuarioinput() muestra tu prompt, espera una línea, y siempre la devuelve como una string, incluso si escribieron un número. ¿Necesitas un número? Conviértelo tú mismo con int() o float() cuando llegue, luego continúa con el tipo correcto.
JunoObteniendo entrada del usuarioinput() siempre devuelve un str, sin inferencia de tipos. Convierte en el límite con int() o float(), y espera un ValueError si el texto no se analiza. Ese patrón recibir-luego-convertir aparece en todas partes donde llegan datos externos.
JunoObteniendo entrada del usuario Todo de input() es un str por diseño, porque Python no puede adivinar qué quisiste decir. Convierte en el punto de entrada y maneja el ValueError cuando no se analiza. Misma forma que cualquier otro lugar donde llegan datos externos.

Escribiendo a stderr

De forma predeterminada, print() escribe en salida estándar: el flujo que aparece en la terminal y fluye a tuberías. Python también tiene error estándar, un flujo separado para diagnósticos y advertencias. Se ven idénticos en una terminal pero son distintos: cuando canalizas la salida de un script en otro comando, solo stdout pasa. Stderr siempre llega a la terminal.

Escribir a stderr usa el argumento file de print(). Eso requiere importar sys, que se cubre en el capítulo Modules. Por ahora, saber que los dos flujos existen y por qué están separados es suficiente.

En práctica

Un cuestionario que se personaliza a partir de la entrada del usuario:

python
name = input("¿Cuál es tu nombre? ")
subject = input("¿Cuál es tu tema favorito? ")

print(f"Bien, {name}. Iniciando tu cuestionario de {subject}.")
print("¡Buena suerte!")

Ambas entradas vuelven como cadenas e van directamente a los f-strings. No es necesaria la conversión porque las estás usando como texto, no como números.

Un convertidor de temperatura con salida tabular alineada:

python
celsius = float(input("Temperatura en Celsius: "))
fahrenheit = celsius * 9 / 5 + 32

print(f"{'Celsius':>12} {'Fahrenheit':>12}")
print(f"{celsius:>12.1f} {fahrenheit:>12.1f}")

float() maneja tanto enteros como decimales del usuario. La especificación :>12 mantiene las columnas alineadas independientemente de cuántos dígitos tengan los números. Prueba ingresando 100 y -40: la salida se mantiene ordenada de cualquier forma.

Usando !r para revelar exactamente qué Python recibió, útil cuando la salida se ve incorrecta:

python
name = input("Ingresa tu nombre: ")
score = float(input("Ingresa tu puntuación (0.0 a 1.0): "))

print(f"Name:   {name!r}")
print(f"Score:  {score!r}")
print()
print(f"Result: {name}: {score:.1%}")

{name} y {name!r} se muestran de forma idéntica cuando la entrada es limpia. La diferencia aparece cuando hay espacios al final u otros caracteres invisibles. Adquirir el hábito de !r durante la depuración hace que los valores inesperados se vean inmediatamente.