Python & AI Tutorials Logo
Programación Python

3. Variables y tipos de datos básicos

En el Capítulo 2 aprendiste a escribir programas simples que imprimen texto, aceptan entrada y realizan operaciones básicas. Sin embargo, esos programas tenían una limitación importante: no podían almacenar información para usarla más tarde ni trabajar con distintos tipos de datos de formas sofisticadas. En este capítulo aprenderás cómo Python almacena y gestiona información usando variables y tipos de datos.

Piensa en las variables como contenedores etiquetados que guardan información. Igual que podrías usar cajas etiquetadas para organizar cosas en tu casa, Python usa variables para organizar y gestionar datos en tus programas. Pero no todos los datos son iguales: un número es fundamentalmente distinto de un texto, y Python necesita saber con qué tipo de dato está trabajando. Ahí es donde entran los tipos de datos.

Al final de este capítulo, entenderás:

  • Cómo crear y nombrar variables correctamente
  • Qué son los tipos de datos y por qué importan
  • Cómo trabajar con números, texto y valores lógicos
  • Cómo convertir entre distintos tipos de datos
  • Cómo representa Python los datos internamente

Estos conceptos forman la base de todo lo que harás en Python, así que los exploraremos a fondo y con muchos ejemplos prácticos.

3.1) Nombrar y crear variables

3.1.1) Qué son las variables y por qué importan

Una variable es un nombre que hace referencia a un valor almacenado en la memoria de tu computadora. Cuando creas una variable, esencialmente estás creando una etiqueta que apunta a algún dato. Esto te permite:

  1. Almacenar información para usarla más adelante en tu programa
  2. Referenciar el mismo valor varias veces sin tener que volver a escribirlo
  3. Actualizar valores mientras tu programa se ejecuta
  4. Hacer tu código legible usando nombres con sentido en lugar de valores crudos

Veamos un ejemplo concreto. Sin variables, si quisieras calcular el área de un rectángulo, podrías escribir:

python
# without_variables.py
print("Rectangle area:", 15 * 8)

Esto funciona, pero ¿y si necesitas usar estas dimensiones varias veces? ¿Y qué representan 15 y 8? Con variables, el código se vuelve más claro y flexible:

python
# with_variables.py
length = 15
width = 8
area = length * width
print("Rectangle area:", area)  # Output: Rectangle area: 120

Ahora el código se documenta por sí mismo: cualquiera que lo lea puede entender inmediatamente que estamos calculando el área de un rectángulo con dimensiones específicas. Si necesitamos cambiar las dimensiones, solo actualizamos las asignaciones de variables al principio.

3.1.2) Crear variables con asignación

En Python, creas una variable usando el operador de asignación (=). La sintaxis básica es:

python
variable_name = value

El signo = no significa "igual" en el sentido matemático. En su lugar, significa "asigna el valor de la derecha al nombre de la izquierda". Esta distinción es crucial. Cuando Python ve esta instrucción:

  1. Evalúa la expresión en el lado derecho de =
  2. Crea o actualiza el nombre de variable en el lado izquierdo
  3. Hace que ese nombre se refiera al valor resultante

Aquí tienes varios ejemplos de creación de variables:

python
# creating_variables.py
age = 25
temperature = 72.5
name = "Alice"
is_student = True
 
print(age)          # Output: 25
print(temperature)  # Output: 72.5
print(name)         # Output: Alice
print(is_student)   # Output: True

Observa que no necesitamos declarar qué tipo de datos va a contener cada variable: Python lo deduce automáticamente a partir del valor que asignas. A esto se le llama tipado dinámico, y hace que Python sea muy flexible y fácil de usar.

También puedes crear múltiples variables en una sola línea usando asignación múltiple:

python
# multiple_assignment.py
x, y, z = 10, 20, 30
print(x)  # Output: 10
print(y)  # Output: 20
print(z)  # Output: 30
 
# You can even assign the same value to multiple variables
a = b = c = 100
print(a, b, c)  # Output: 100 100 100

La primera forma (llamada desempaquetado de tuplas—aprenderemos sobre tuplas en el Capítulo 14) asigna cada valor a su variable correspondiente en orden. La segunda forma asigna el mismo valor a las tres variables.

3.1.3) Reglas y convenciones para nombrar variables

Python tiene reglas específicas sobre lo que constituye un nombre de variable válido. Algunas de estas son requisitos (reglas que debes seguir), mientras que otras son convenciones (guías que hacen tu código más legible y consistente con otro código Python).

Requisitos (debes seguirlos):

  1. Debe empezar con una letra (a-z, A-Z) o guion bajo (_): Los nombres de variable no pueden empezar con un dígito.
  2. Pueden contener letras, dígitos y guiones bajos: Después del primer carácter, puedes usar letras, números y guiones bajos en cualquier combinación.
  3. No pueden contener espacios ni caracteres especiales: Espacios, guiones y la mayoría de signos de puntuación no están permitidos.
  4. No pueden ser una palabra clave de Python: Python reserva ciertas palabras para su propio uso (como if, for, while, def, etc.).
  5. Distinguen mayúsculas de minúsculas: age, Age y AGE son tres variables diferentes.

Aquí tienes ejemplos de nombres de variables válidos e inválidos:

python
# valid_names.py
# Valid variable names
user_age = 30
firstName = "John"
total_2024 = 1000
_private = "hidden"
x = 5
MAX_SIZE = 100
 
# Invalid variable names (these will cause errors)
# 2nd_place = "silver"      # Error: starts with digit
# user-name = "alice"       # Error: contains hyphen
# total amount = 500        # Error: contains space
# class = "Python 101"      # Error: 'class' is a keyword

Convenciones (deberías seguirlas para mejorar la legibilidad):

  1. Usa minúsculas con guiones bajos para variables normales: Este estilo se llama snake_case y es el estándar en Python.

    python
    user_age = 25
    total_price = 99.99
    is_valid = True
  2. Usa MAYÚSCULAS para constantes: Valores que no deberían cambiar durante la ejecución del programa.

    python
    MAX_ATTEMPTS = 3
    PI = 3.14159
    DEFAULT_COLOR = "blue"
  3. Usa nombres descriptivos: Los nombres de variables deberían indicar claramente lo que representan.

    python
    # Good: clear and descriptive
    student_count = 30
    average_temperature = 72.5
     
    # Poor: unclear abbreviations
    sc = 30
    avg_tmp = 72.5
     
    # Poor: too generic
    x = 30
    data = 72.5
  4. Evita nombres de una sola letra salvo en casos específicos: Letras sueltas como i, j, k son aceptables como contadores de bucle (loop) (que veremos en el Capítulo 11), y x, y, z están bien para coordenadas. En otros casos, usa nombres descriptivos.

  5. No uses nombres que oculten funciones integradas: Aunque Python lo permite, evita usar nombres como list, str, int, print, etc., ya que son nombres de funciones integradas.

Veamos un ejemplo práctico que demuestra buenas prácticas de nombres:

python
# good_naming.py
# Constants at the top
SALES_TAX_RATE = 0.08
DISCOUNT_THRESHOLD = 100
 
# Descriptive variable names
item_price = 75.00
quantity = 3
subtotal = item_price * quantity
 
# Clear boolean variable
qualifies_for_discount = subtotal >= DISCOUNT_THRESHOLD
 
if qualifies_for_discount:
    discount = subtotal * 0.10
    subtotal = subtotal - discount
    print("Discount applied: $", discount)
 
tax = subtotal * SALES_TAX_RATE
total = subtotal + tax
 
print("Subtotal: $", subtotal)
print("Tax: $", tax)
print("Total: $", total)
# Output:
# Subtotal: $ 202.5
# Tax: $ 16.2
# Total: $ 218.7

Observa cómo los nombres de las variables hacen que el código se documente por sí mismo. Incluso sin comentarios, puedes entender qué está calculando el programa.

3.1.4) Usar variables en expresiones

Una vez que has creado una variable, puedes usarla en cualquier lugar donde usarías el valor que representa. Python sustituirá automáticamente el valor actual de la variable cuando evalúe expresiones:

python
# using_variables.py
# Create some variables
hours_worked = 40
hourly_rate = 25.50
 
# Use variables in calculations
gross_pay = hours_worked * hourly_rate
print("Gross pay:", gross_pay)  # Output: Gross pay: 1020.0
 
# Use variables in other expressions
bonus = gross_pay * 0.10
total_pay = gross_pay + bonus
print("Total with bonus:", total_pay)  # Output: Total with bonus: 1122.0
 
# Use variables in strings (we'll learn more about this in Chapter 5)
message = "You worked " + str(hours_worked) + " hours"
print(message)  # Output: You worked 40 hours

Las variables también se pueden usar con las funciones que aprendiste en el Capítulo 2:

python
# variables_with_functions.py
name = input("What is your name? ")
age = input("What is your age? ")
 
greeting = "Hello, " + name + "!"
print(greeting)
 
age_next_year = int(age) + 1
print("Next year you will be", age_next_year, "years old.")
# If user enters "Alice" and "25":
# Output: Hello, Alice!
# Output: Next year you will be 26 years old.

Este ejemplo también muestra un concepto importante: la función input() siempre devuelve texto (un string), así que si quieres hacer operaciones matemáticas con ese valor, primero debes convertirlo a un número. Exploraremos este proceso de conversión en detalle más adelante en este capítulo (Sección 3.7).

3.2) Asignación y reasignación de variables

3.2.1) Entender la asignación

Cuando asignas un valor a una variable, Python crea una conexión entre el nombre de la variable y el valor en memoria. Es importante entender que la variable no "contiene" el valor en un sentido físico; más bien, es un nombre que se refiere o apunta a un valor almacenado en otro lugar de la memoria.

Imagina una nota adhesiva con un nombre escrito, pegada a una caja que contiene el valor real. La variable (la nota) no es el valor en sí: solo indica dónde está almacenado. Cuando reasignas la variable, estás moviendo la nota adhesiva para que apunte a otra caja diferente, no cambiando lo que hay en la caja original.

Esta distinción se vuelve importante cuando hablamos de reasignación. Veamos qué ocurre cuando asignas y reasignas variables:

python
# assignment_basics.py
x = 10
print(x)  # Output: 10
 
# Reassign x to a new value
x = 20
print(x)  # Output: 20
 
# The old value (10) is gone; x now refers to 20

Esto es lo que ocurrió paso a paso:

  1. x = 10: Python crea el valor entero 10 en memoria y hace que el nombre x se refiera a él
  2. print(x): Python busca a qué se refiere x (10) y lo imprime
  3. x = 20: Python crea el valor entero 20 en memoria y hace que x se refiera ahora a este nuevo valor
  4. print(x): Python busca a qué se refiere x (ahora 20) y lo imprime

El valor original 10 sigue existiendo temporalmente en memoria, pero como ninguna variable se refiere ya a él, el sistema de gestión automática de memoria de Python (llamado recolección de basura, o garbage collection) acabará eliminándolo.

3.2.2) Reasignación y actualización de variables

Uno de los patrones más comunes en programación es actualizar una variable en función de su valor actual. Por ejemplo, podrías querer incrementar un contador, sumar a un total acumulado o modificar un valor en base a algún cálculo:

python
# updating_variables.py
score = 0
print("Initial score:", score)  # Output: Initial score: 0
 
# Add 10 points
score = score + 10
print("After first update:", score)  # Output: After first update: 10
 
# Add 5 more points
score = score + 5
print("After second update:", score)  # Output: After second update: 15
 
# Double the score
score = score * 2
print("After doubling:", score)  # Output: After doubling: 30

Desglosemos lo que pasa en score = score + 10:

  1. Python evalúa el lado derecho: score + 10
  2. Busca el valor actual de score (0)
  3. Calcula 0 + 10, obteniendo 10
  4. Asigna este nuevo valor (10) a score
  5. Ahora score se refiere a 10 en lugar de a 0

Este patrón es tan común que Python proporciona operadores abreviados para él, que veremos en el Capítulo 4 (Sección 4.3). Pero por ahora, es importante entender la forma completa porque muestra claramente el orden de las operaciones: evalúa completamente el lado derecho y luego asigna al lado izquierdo.

3.2.3) Las variables son independientes

Cuando asignas una variable a otra, Python copia la referencia, no el valor en sí (para tipos simples como números y strings). Sin embargo, para los tipos básicos que estamos viendo en este capítulo, las variables se comportan de forma independiente después de la asignación:

python
# independent_variables.py
a = 10
b = a  # b now refers to the same value as a (10)
print("a:", a)  # Output: a: 10
print("b:", b)  # Output: b: 10
 
# Change a
a = 20
print("After changing a:")
print("a:", a)  # Output: a: 20
print("b:", b)  # Output: b: 10 (unchanged!)

Cuando asignamos b = a, hicimos que b se refiriera al mismo valor al que a se refería en ese momento (10). Cuando más tarde cambiamos a para que se refiriera a 20, b no se vio afectada: sigue refiriéndose a 10.

Este comportamiento es sencillo para números y strings, pero se vuelve más complejo con colecciones como listas (list) y diccionarios (dict). Exploraremos esto a fondo en el Capítulo 17 cuando hablemos del modelo de objetos de Python y de las referencias.

3.2.4) Usar variables antes de asignarlas

Un error común de principiantes es intentar usar una variable antes de haberle asignado un valor. Python lanzará un NameError si intentas hacer esto:

python
# undefined_variable.py
print(total)  # Error: NameError: name 'total' is not defined

Este error ocurre porque Python no sabe a qué se refiere total: todavía no la has creado. La solución es sencilla: asigna un valor a la variable antes de usarla:

python
# defined_variable.py
total = 0  # Initialize the variable first
print(total)  # Output: 0
 
# Now we can update it
total = total + 10
print(total)  # Output: 10

Este patrón de inicializar una variable (darle un valor inicial) antes de usarla es fundamental en programación. Veremos muchos ejemplos de esto a lo largo del libro, especialmente al trabajar con contadores y acumuladores en bucles (Capítulo 10).

3.2.5) Intercambiar valores de variables

Una operación común es intercambiar los valores de dos variables. En muchos lenguajes de programación, esto requiere una variable temporal:

python
# swap_with_temp.py
x = 10
y = 20
print("Before swap: x =", x, ", y =", y)  # Output: Before swap: x = 10 , y = 20
 
# Swap using a temporary variable
temp = x    # Save x's value
x = y       # Put y's value in x
y = temp    # Put saved value in y
 
print("After swap: x =", x, ", y =", y)  # Output: After swap: x = 20 , y = 10

Sin embargo, Python proporciona una forma más elegante usando asignación simultánea:

python
# swap_pythonic.py
x = 10
y = 20
print("Before swap: x =", x, ", y =", y)  # Output: Before swap: x = 10 , y = 20
 
# Swap in one line
x, y = y, x
 
print("After swap: x =", x, ", y =", y)  # Output: After swap: x = 20 , y = 10

Esto funciona porque Python evalúa todo el lado derecho (y, x) antes de hacer ninguna asignación. Así que crea una estructura temporal que contiene los valores de y y x, y luego desempaqueta esos valores en x y y respectivamente. Este es un buen ejemplo de la filosofía de Python de hacer que las operaciones comunes sean simples y legibles.

3.3) El concepto de tipos de datos y type()

3.3.1) Qué son los tipos de datos

Un tipo de datos (o simplemente tipo) define qué clase de dato representa un valor y qué operaciones se pueden realizar sobre él. Piensa en los tipos de datos como categorías que le dicen a Python cómo interpretar y trabajar con distintos tipos de información.

Por ejemplo:

  • El número 42 es un entero (número entero)
  • El número 3.14 es un número de coma flotante (número con punto decimal)
  • El texto "Hello" es un string (secuencia de caracteres)
  • El valor True es un booleano (valor lógico verdadero/falso)

¿Por qué importan los tipos de datos? Porque tipos distintos soportan operaciones distintas:

python
# type_operations.py
# You can add numbers
result1 = 10 + 5
print(result1)  # Output: 15
 
# You can also "add" strings (concatenation)
result2 = "Hello" + " " + "World"
print(result2)  # Output: Hello World
 
# But you can't add a number and a string directly
# result3 = 10 + "5"  # Error: TypeError: unsupported operand type(s)

El error del último ejemplo ocurre porque Python no sabe cómo sumar un número y un string: son tipos de datos fundamentalmente diferentes. ¿Debería convertir el número a texto y concatenarlo? ¿Debería convertir el texto a número y sumar matemáticamente? Python requiere que seas explícito sobre lo que quieres haciendo que conviertas uno de los valores para que coincida con el tipo del otro (veremos cómo en la Sección 3.7).

3.3.2) Usar type() para comprobar tipos de datos

Python proporciona una función integrada llamada type() que te dice de qué tipo es un valor o variable. Esto es extremadamente útil para entender tus datos y depurar problemas:

python
# checking_types.py
# Check types of literal values
print(type(42))        # Output: <class 'int'>
print(type(3.14))      # Output: <class 'float'>
print(type("Hello"))   # Output: <class 'str'>
print(type(True))      # Output: <class 'bool'>
 
# Check types of variables
age = 25
name = "Alice"
temperature = 98.6
is_valid = False
 
print(type(age))         # Output: <class 'int'>
print(type(name))        # Output: <class 'str'>
print(type(temperature)) # Output: <class 'float'>
print(type(is_valid))    # Output: <class 'bool'>

La salida <class 'int'> significa "este valor pertenece a la clase (tipo) llamada int". En Python, los tipos son en realidad clases (aprenderemos sobre clases en detalle en la Parte VIII), pero por ahora puedes pensar en estos términos como intercambiables.

3.3.3) Tipado dinámico en Python

Python es un lenguaje de tipado dinámico (dynamically typed), lo que significa:

  1. Las variables no tienen tipos fijos: Una variable puede referirse a valores de distintos tipos en distintos momentos
  2. Los tipos se determinan en tiempo de ejecución: Python averigua los tipos cuando el programa se ejecuta, no cuando escribes el código
  3. No declaras los tipos explícitamente: A diferencia de otros lenguajes, no necesitas decir "esta variable contendrá un entero"

Aquí tienes un ejemplo de tipado dinámico en acción:

python
# dynamic_typing.py
x = 42
print(x, "is of type", type(x))  # Output: 42 is of type <class 'int'>
 
x = "Hello"
print(x, "is of type", type(x))  # Output: Hello is of type <class 'str'>
 
x = 3.14
print(x, "is of type", type(x))  # Output: 3.14 is of type <class 'float'>

Observa cómo x puede referirse a distintos tipos de valores en diferentes puntos del programa. Python no se queja: simplemente actualiza a qué tipo se refiere x en ese momento.

Aunque esta flexibilidad es cómoda, también significa que debes tener cuidado. Si esperas que una variable contenga un número pero en realidad contiene un string, podrías obtener errores inesperados:

python
# type_confusion.py
value = "100"  # This is a string, not a number!
 
# Trying to do math with it will fail
# result = value + 50  # Error: TypeError: can only concatenate str to str
 
# You need to convert it first
result = int(value) + 50
print(result)  # Output: 150

Por eso es crucial entender los tipos de datos: te ayuda a predecir qué operaciones funcionarán y a detectar errores antes de que se conviertan en fallos en tiempo de ejecución.

3.3.4) Panorama de los tipos integrados de Python

Python tiene varios tipos de datos integrados. En este capítulo nos centraremos en los más fundamentales:

Tipos integrados de Python

Tipos numéricos

Tipo de texto

Tipo booleano

Tipo None

Tipos de colección

int: enteros

float: números decimales

complex: números complejos

str: texto/strings

bool: True/False

NoneType: None

list, tuple, dict, set...

En este capítulo, cubriremos:

  • int: Números enteros (enteros)
  • float: Números de coma flotante (números con punto decimal)
  • str: Strings (texto)
  • bool: Valores booleanos (True y False)
  • NoneType: El valor especial None

Mencionaremos brevemente los números complex (números con componente imaginaria), pero rara vez se necesitan en programación cotidiana. Los tipos de colección (como listas (list), tuplas (tuple), diccionarios (dict) y conjuntos (set)) son tan importantes que les hemos dedicado capítulos completos en la Parte IV.

3.3.5) Comprobación de tipos en la práctica

Entender los tipos se vuelve especialmente importante al trabajar con entrada de usuario o datos de fuentes externas. Recuerda que input() siempre devuelve un string, incluso si el usuario escribe un número:

python
# input_types.py
user_input = input("Enter a number: ")
print("You entered:", user_input)
print("Type:", type(user_input))  # Output: Type: <class 'str'>
 
# Even if user types "42", it's still a string!
# To use it as a number, convert it:
number = int(user_input)
print("As a number:", number)
print("Type:", type(number))  # Output: Type: <class 'int'>
 
# Now we can do math with it
doubled = number * 2
print("Doubled:", doubled)

Cuando ejecutes este programa y escribas 42, verás:

Enter a number: 42
You entered: 42
Type: <class 'str'>
As a number: 42
Type: <class 'int'>
Doubled: 84

Esto demuestra un punto crucial: el string "42" y el entero 42 son cosas diferentes en Python, aunque se vean similares al imprimirlos. El string es una secuencia de dos caracteres ('4' y '2'), mientras que el entero es un valor numérico que puede usarse en operaciones matemáticas.

3.4) Números enteros y de coma flotante

3.4.1) Enteros (int)

Un entero (tipo int) es un número entero sin punto decimal. Los enteros pueden ser positivos, negativos o cero, y en Python 3 pueden ser arbitrariamente grandes, limitados solo por la memoria disponible de tu computadora.

python
# integers.py
# Positive integers
age = 25
year = 2024
population = 8000000000
 
# Negative integers
temperature = -15
debt = -5000
 
# Zero
balance = 0
 
# Very large integers (Python handles these easily)
huge_number = 123456789012345678901234567890
print(huge_number)  # Output: 123456789012345678901234567890
print(type(huge_number))  # Output: <class 'int'>

Python te permite escribir números grandes con guiones bajos para mejorar la legibilidad. Los guiones bajos son ignorados por Python, pero hacen los números más fáciles de leer para las personas:

python
# readable_numbers.py
# These are all the same number
million = 1000000
million = 1_000_000  # Much easier to read!
 
# Works with any size
population = 8_000_000_000
national_debt = 31_000_000_000_000
 
print(million)      # Output: 1000000 (underscores not shown in output)
print(population)   # Output: 8000000000

También puedes escribir enteros en distintas bases numéricas usando prefijos especiales:

python
# number_bases.py
# Binary (base 2) - prefix 0b
binary = 0b1010  # This is 10 in decimal
print(binary)  # Output: 10
 
# Octal (base 8) - prefix 0o
octal = 0o12  # This is 10 in decimal
print(octal)  # Output: 10
 
# Hexadecimal (base 16) - prefix 0x
hexadecimal = 0xFF  # This is 255 in decimal
print(hexadecimal)  # Output: 255

Estas bases alternativas son útiles en ciertos contextos (como trabajar con colores en diseño web o programación de bajo nivel), pero para la mayoría de la programación cotidiana usarás enteros decimales normales.

3.4.2) Números de coma flotante (float)

Un número de coma flotante (tipo float) es un número con punto decimal. Los floats se usan para representar números reales, es decir, valores que no tienen por qué ser enteros:

python
# floats.py
# Numbers with decimal points
price = 19.99
temperature = 98.6
pi = 3.14159
 
# Very small numbers
electron_mass = 0.00000000000000000000000000000091093837
 
# Very large numbers
speed_of_light = 299792458.0
 
print(price)           # Output: 19.99
print(temperature)     # Output: 98.6
print(electron_mass)   # Output: 9.1093837e-31 (scientific notation)
print(speed_of_light)  # Output: 299792458.0

Observa que los floats muy pequeños o muy grandes se muestran en notación científica (también llamada notación exponencial). La notación 9.1093837e-31 significa "9.1093837 × 10⁻³¹" o "9.1093837 dividido entre 10 elevado a 31".

También puedes escribir floats usando notación científica directamente:

python
# scientific_notation.py
# These are equivalent
avogadro = 602214076000000000000000.0
avogadro = 6.02214076e23  # Much more readable!
 
# Small numbers
planck = 0.000000000000000000000000000000000662607015
planck = 6.62607015e-34  # Much more readable!
 
print(avogadro)  # Output: 6.02214076e+23
print(planck)    # Output: 6.62607015e-34

La e (o E) significa "exponente". El número después de e indica cuántas posiciones mover el punto decimal (positivo hacia la derecha, negativo hacia la izquierda).

3.4.3) Entero vs float: diferencias importantes

Aunque enteros y floats representan números, tienen diferencias importantes:

1. Precisión y representación:

Los enteros son exactos: el valor 42 es exactamente 42, sin aproximación. Los floats, en cambio, son aproximaciones debido a cómo los ordenadores almacenan números decimales en binario:

python
# float_precision.py
# This might surprise you!
result = 0.1 + 0.2
print(result)  # Output: 0.30000000000000004
 
# The result isn't exactly 0.3 due to floating-point representation
print(result == 0.3)  # Output: False

Esto no es un fallo: es una limitación fundamental de cómo los ordenadores representan números decimales. Hablaremos de esto con más detalle en el Capítulo 4 (Sección 4.10), pero por ahora solo ten en cuenta que los cálculos con floats pueden no ser perfectamente precisos.

2. Operaciones y resultados:

Cuando realizas operaciones con enteros y floats, Python sigue reglas específicas:

python
# int_float_operations.py
# Integer operations
int_result = 10 + 5
print(int_result, type(int_result))  # Output: 15 <class 'int'>
 
# Float operations
float_result = 10.0 + 5.0
print(float_result, type(float_result))  # Output: 15.0 <class 'float'>
 
# Mixed operations: result is always float
mixed_result = 10 + 5.0
print(mixed_result, type(mixed_result))  # Output: 15.0 <class 'float'>
 
# Division always returns float, even with integers
division_result = 10 / 5
print(division_result, type(division_result))  # Output: 2.0 <class 'float'>

La regla clave: cualquier operación que involucre al menos un float produce un resultado float. Esto tiene sentido porque los floats pueden representar un rango más amplio de valores (incluidos números no enteros), así que Python "promociona" el resultado al tipo más general.

3. Memoria y rendimiento:

Los enteros usan menos memoria y son más rápidos de calcular que los floats. En la mayoría de los programas, esta diferencia es insignificante, pero puede importar en aplicaciones de alto rendimiento o cuando se trabaja con conjuntos de datos muy grandes.

3.4.4) Cuándo usar int y cuándo usar float

Aquí tienes pautas prácticas para elegir entre enteros y floats:

Usa enteros cuando:

  • Cuentas elementos discretos (personas, objetos, iteraciones)
  • Representas cantidades exactas que no pueden ser fraccionarias (número de estudiantes, número de clics)
  • Trabajas con índices o posiciones en secuencias
  • Necesitas aritmética exacta
python
# use_integers.py
student_count = 30  # Can't have 30.5 students
page_number = 42    # Can't be on page 42.7
loop_counter = 0    # Counting iterations

Usa floats cuando:

  • Representas medidas (temperatura, distancia, peso)
  • Trabajas con dinero (aunque hay que tener cuidado con la precisión—lo veremos en el Capítulo 4)
  • Calculas ratios, porcentajes o promedios
  • Te bastan valores aproximados
python
# use_floats.py
temperature = 72.5     # Temperature can be fractional
price = 19.99          # Money amounts have cents
average_score = 87.3   # Averages are often fractional
percentage = 0.15      # 15% as a decimal

3.5) Literales string y booleanos (vista previa rápida)

En esta sección presentaremos brevemente otros dos tipos de datos fundamentales: strings y booleanos. Veremos los strings en mucha más profundidad en los Capítulos 5 y 6, y los booleanos en detalle en el Capítulo 7, pero necesitas una comprensión básica de ellos desde ahora para poder escribir incluso programas simples.

3.5.1) Conceptos básicos de strings

Un string (tipo str) es una secuencia de caracteres; esencialmente, texto. Creas strings encerrando texto entre comillas. Python acepta comillas simples (') o dobles ("):

python
# string_basics.py
# Single quotes
name = 'Alice'
message = 'Hello, World!'
 
# Double quotes (exactly equivalent)
name = "Alice"
message = "Hello, World!"
 
# Print them
print(name)     # Output: Alice
print(message)  # Output: Hello, World!
print(type(name))  # Output: <class 'str'>

Tanto las comillas simples como las dobles funcionan de forma idéntica: elige las que prefieras, pero sé consistente dentro de tu código. Muchos programadores de Python prefieren las comillas dobles porque son más comunes en otros lenguajes, pero las simples son igualmente válidas.

¿Por qué existen ambas? La principal razón es la comodidad cuando tu string contiene comillas:

python
# quotes_in_strings.py
# Use double quotes when string contains single quotes
sentence = "It's a beautiful day!"
print(sentence)  # Output: It's a beautiful day!
 
# Use single quotes when string contains double quotes
speech = 'She said, "Hello!"'
print(speech)  # Output: She said, "Hello!"
 
# Or use escape sequences (we'll learn more in Chapter 5)
sentence = 'It\'s a beautiful day!'  # \' means a literal single quote
speech = "She said, \"Hello!\""     # \" means a literal double quote

Los strings pueden estar vacíos (no contener caracteres):

python
# empty_string.py
empty = ""
also_empty = ''
 
print(empty)            # Output: (nothing—it's empty!)
print(len(empty))       # Output: 0 (we'll learn about len() later)
print(type(empty))      # Output: <class 'str'>

Puedes combinar strings usando el operador + (llamado concatenación):

python
# string_concatenation.py
first_name = "John"
last_name = "Doe"
full_name = first_name + " " + last_name
print(full_name)  # Output: John Doe
 
# Be careful: you can't concatenate strings and numbers directly
age = 25
# message = "I am " + age + " years old"  # Error: TypeError
 
# Convert the number to a string first
message = "I am " + str(age) + " years old"
print(message)  # Output: I am 25 years old

Exploraremos los strings mucho más a fondo en los Capítulos 5 y 6, incluyendo secuencias de escape, métodos de string, formateo y procesamiento de texto. Por ahora, solo recuerda que los strings representan texto y se crean con comillas.

3.5.2) Conceptos básicos de booleanos

Un booleano (tipo bool) es un valor lógico que puede ser True o False. Estos son los únicos dos valores booleanos en Python y se usan para representar verdad y falsedad en operaciones lógicas:

python
# boolean_basics.py
# Boolean literals
is_sunny = True
is_raining = False
 
print(is_sunny)         # Output: True
print(is_raining)       # Output: False
print(type(is_sunny))   # Output: <class 'bool'>

Importante: Los valores booleanos True y False deben ir con mayúscula inicial exactamente como se muestra. Python distingue mayúsculas de minúsculas, así que true, TRUE, false y FALSE no funcionarán:

python
# boolean_case.py
correct = True    # Correct
# wrong = true    # Error: NameError: name 'true' is not defined
# wrong = TRUE    # Error: NameError: name 'TRUE' is not defined

Los booleanos suelen provenir de comparaciones u operaciones lógicas:

python
# boolean_from_comparisons.py
age = 25
 
# Comparison operators produce boolean results
is_adult = age >= 18
print(is_adult)  # Output: True
 
is_senior = age >= 65
print(is_senior)  # Output: False
 
# You can use booleans in conditions (we'll learn more in Chapter 8)
if is_adult:
    print("You can vote!")  # Output: You can vote!
 
if is_senior:
    print("You get a senior discount!")  # (no output—condition is False)

Operadores de comparación comunes que producen booleanos:

  • == : igual que
  • != : distinto de
  • < : menor que
  • > : mayor que
  • <= : menor o igual que
  • >= : mayor o igual que
python
# comparison_operators.py
x = 10
y = 20
 
print(x == y)   # Output: False (10 is not equal to 20)
print(x != y)   # Output: True (10 is not equal to 20)
print(x < y)    # Output: True (10 is less than 20)
print(x > y)    # Output: False (10 is not greater than 20)
print(x <= 10)  # Output: True (10 is less than or equal to 10)
print(y >= 20)  # Output: True (20 is greater than or equal to 20)

Nota importante: No confundas = (asignación) con == (comparación):

  • x = 10 significa "asigna el valor 10 a x"
  • x == 10 significa "comprueba si x es igual a 10" (produce True o False)
python
# assignment_vs_comparison.py
x = 10        # Assignment: x now refers to 10
result = (x == 10)  # Comparison: is x equal to 10?
print(result)  # Output: True
 
# This is a common mistake for beginners:
# if x = 10:  # Error: SyntaxError (can't use assignment in if condition)
if x == 10:   # Correct: comparison
    print("x is 10")  # Output: x is 10

Exploraremos los booleanos con mucho más detalle en el Capítulo 7, incluyendo operadores lógicos (and, or, not), verdad y falsedad (truthiness y falsiness), y cómo usa Python los booleanos en condiciones. Por ahora, solo recuerda que los booleanos representan valores True/False y suelen provenir de comparaciones.

3.5.3) Strings y booleanos en contexto

Veamos cómo funcionan juntos strings y booleanos en un ejemplo práctico sencillo:

python
# strings_booleans_example.py
# Get user input
name = input("What is your name? ")
age_input = input("What is your age? ")
 
# Convert age to integer
age = int(age_input)
 
# Create boolean conditions
is_adult = age >= 18
is_child = age < 13
 
# Build messages using strings
if is_adult:
    status = "adult"
else:
    status = "minor"
 
# Combine everything in output
print("Hello, " + name + "!")
print("You are an " + status + ".")
 
if is_child:
    print("You are a child.")
 
# When user enters "Alice" and "16":
# Output: Hello, Alice!
# Output: You are a minor.

Este ejemplo demuestra cómo distintos tipos de datos trabajan juntos: strings para texto, enteros para números y booleanos para decisiones lógicas. Esta interacción entre tipos es fundamental en toda programación.

3.6) El valor None y sus usos

3.6.1) Qué es None

Python tiene un valor especial llamado None (tipo NoneType) que representa la ausencia de un valor. Es la forma que tiene Python de decir "no hay nada aquí" o "esto aún no tiene valor".

python
# none_basics.py
result = None
print(result)        # Output: None
print(type(result))  # Output: <class 'NoneType'>

None no es lo mismo que cero, ni que un string vacío, ni que False: es un valor distinto que significa específicamente "sin valor":

python
# none_vs_others.py
x = None
y = 0
z = ""
w = False
 
print(x)  # Output: None
print(y)  # Output: 0
print(z)  # Output: (empty—nothing prints)
print(w)  # Output: False
 
# They're all different types
print(type(x))  # Output: <class 'NoneType'>
print(type(y))  # Output: <class 'int'>
print(type(z))  # Output: <class 'str'>
print(type(w))  # Output: <class 'bool'>

3.6.2) Cuándo se usa None

None aparece en varias situaciones comunes:

1. Como marcador de posición para valores que asignarás más tarde:

python
# none_placeholder.py
# Initialize variables that will be assigned later
user_name = None
user_age = None
 
# Later in the program, after getting user input:
user_name = input("Enter your name: ")
user_age = int(input("Enter your age: "))
 
print("Name:", user_name)
print("Age:", user_age)

2. Como valor de retorno por defecto de funciones que no devuelven nada explícitamente:

Las funciones que veremos en el Capítulo 19 pueden devolver valores. Si una función no devuelve nada explícitamente, Python devuelve automáticamente None:

python
# none_from_function.py
# The print() function returns None
result = print("Hello!")  # Output: Hello!
print(result)             # Output: None
print(type(result))       # Output: <class 'NoneType'>

Esto puede parecer raro, pero es útil. Significa que todas las funciones devuelven algo, incluso si ese algo es "ningún valor significativo".

3. Para representar datos opcionales o ausentes:

python
# none_optional.py
# Representing optional middle name
first_name = "John"
middle_name = None  # No middle name
last_name = "Doe"
 
if middle_name is None:
    full_name = first_name + " " + last_name
else:
    full_name = first_name + " " + middle_name + " " + last_name
 
print(full_name)  # Output: John Doe

3.6.3) Comprobar si algo es None

Para comprobar si un valor es None, usa el operador is (no ==):

python
# checking_none.py
value = None
 
# Correct way: use 'is'
if value is None:
    print("Value is None")  # Output: Value is None
 
# Also correct: use 'is not'
if value is not None:
    print("Value has a value")
else:
    print("Value is None")  # Output: Value is None
 
# While == works, 'is' is preferred for None
if value == None:  # This works but is not idiomatic Python
    print("Value is None")  # Output: Value is None

¿Por qué usar is en lugar de ==? El operador is comprueba si dos nombres se refieren exactamente al mismo objeto en memoria (veremos más sobre esto en el Capítulo 17). Como solo existe un objeto None en Python, is es a la vez más eficiente y más preciso para esta comprobación. Usar is None es el patrón estándar en Python.

3.6.4) None en uso práctico

Aquí tienes un ejemplo práctico que muestra cómo None es útil en programas reales:

python
# none_practical.py
# Simulate looking up a user's age
# (In real programs, we'd use functions and dictionaries from later chapters)
 
user_name = input("Enter a name (Alice, Bob, or Charlie): ")
 
# Check each name and assign age or None
if user_name == "Alice":
    user_age = 25
elif user_name == "Bob":
    user_age = 30
elif user_name == "Charlie":
    user_age = 35
else:
    user_age = None  # User not found
 
# Check if we found the user
if user_age is not None:
    print(user_name, "is", user_age, "years old")
else:
    print(user_name, "not found")
 
# When user enters "Alice":
# Output: Alice is 25 years old
# When user enters "David":
# Output: David not found

En este ejemplo, None indica claramente "usuario no encontrado", lo cual es distinto de encontrar un usuario con edad 0 (que sería una edad válida para un recién nacido).

3.6.5) None vs valores vacíos

Es importante distinguir None de valores vacíos:

python
# none_vs_empty.py
# These are all different
nothing = None
zero = 0
empty_string = ""
# Note: We'll learn about lists in Chapter 13
# empty_list = []
 
print(nothing is None)       # Output: True
print(zero is None)          # Output: False
print(empty_string is None)  # Output: False
 
# None means "no value"
# 0 means "the number zero"
# "" means "text with no characters"

Cada uno de estos representa un concepto distinto:

  • None: ausencia de valor
  • 0: un valor numérico específico (cero)
  • "": un string que existe pero no contiene caracteres

Entender esta distinción te ayudará a escribir programas más claros y correctos.

3.7) Conversión básica de tipos con int(), float() y str()

3.7.1) Por qué es necesaria la conversión de tipos

Como hemos visto, Python tiene reglas estrictas sobre qué operaciones funcionan con qué tipos. No puedes sumar un número y un string, multiplicar un string por un float, ni realizar operaciones matemáticas con texto. Cuando necesitas usar un valor como otro tipo distinto, debes convertirlo explícitamente.

La conversión de tipos (también llamada casting de tipos) es el proceso de cambiar un valor de un tipo a otro. Python proporciona funciones integradas para las conversiones más comunes:

  • int(): Convierte a entero
  • float(): Convierte a número de coma flotante
  • str(): Convierte a string

Veamos cada una en detalle.

3.7.2) Convertir a entero con int()

La función int() convierte un valor a entero. Estos son los casos de uso principales:

Convertir floats a enteros:

python
# float_to_int.py
# int() truncates (cuts off) the decimal part
x = int(3.14)
y = int(3.99)
z = int(-2.7)
 
print(x)  # Output: 3 (not 4—it doesn't round!)
print(y)  # Output: 3 (not 4—it truncates!)
print(z)  # Output: -2 (truncates toward zero)

Importante: int() no redondea: simplemente elimina la parte decimal (trunca hacia cero). Esto confunde a muchos principiantes que esperan que int(3.9) devuelva 4.

Convertir strings a enteros:

Esto es extremadamente común al trabajar con entrada de usuario:

python
# string_to_int.py
# Convert string containing a number
age_str = "25"
age_int = int(age_str)
 
print(age_str, type(age_str))  # Output: 25 <class 'str'>
print(age_int, type(age_int))  # Output: 25 <class 'int'>
 
# Now we can do math with it
next_year = age_int + 1
print("Next year:", next_year)  # Output: Next year: 26
 
# Practical example with input()
user_age = int(input("Enter your age: "))
print("In 10 years, you'll be", user_age + 10)

Qué pasa con conversiones inválidas

Si intentas convertir un string que no representa un entero válido, Python lanza un ValueError:

python
# invalid_int_conversion.py
# These work
print(int("123"))    # Output: 123
print(int("-456"))   # Output: -456
print(int("  789 ")) # Output: 789 (whitespace is ignored)
 
# These don't work
# print(int("12.5"))   # Error: ValueError: invalid literal for int()
# print(int("hello"))  # Error: ValueError: invalid literal for int()
# print(int("12 34"))  # Error: ValueError: invalid literal for int()

Aprenderemos a manejar estos errores de forma elegante en el Capítulo 27 cuando veamos el manejo de excepciones. Por ahora, solo ten en cuenta que debes asegurarte de que tus strings contengan representaciones enteras válidas antes de convertirlos.

Convertir booleanos a enteros:

Los booleanos se pueden convertir a enteros, donde True se convierte en 1 y False en 0:

python
# bool_to_int.py
print(int(True))   # Output: 1
print(int(False))  # Output: 0
 
# This is sometimes useful in calculations
is_premium = True
is_student = False
 
# Calculate discount (10% for premium, 5% for students)
discount = int(is_premium) * 0.10 + int(is_student) * 0.05
print("Discount:", discount)  # Output: Discount: 0.1

Sin embargo, usar booleanos directamente en aritmética generalmente se desaconseja porque hace el código menos legible. Hablaremos más de esto en el Capítulo 7.

3.7.3) Convertir a float con float()

La función float() convierte un valor a número de coma flotante:

Convertir enteros a floats:

python
# int_to_float.py
x = float(42)
y = float(-17)
z = float(0)
 
print(x, type(x))  # Output: 42.0 <class 'float'>
print(y, type(y))  # Output: -17.0 <class 'float'>
print(z, type(z))  # Output: 0.0 <class 'float'>

Convertir strings a floats:

python
# string_to_float.py
# Convert string containing decimal number
price_str = "19.99"
price_float = float(price_str)
 
print(price_str, type(price_str))    # Output: 19.99 <class 'str'>
print(price_float, type(price_float))  # Output: 19.99 <class 'float'>
 
# Strings without decimal points work too
x = float("42")
print(x, type(x))  # Output: 42.0 <class 'float'>
 
# Scientific notation strings work
big = float("1.5e10")
print(big)  # Output: 15000000000.0

Conversiones inválidas:

Igual que int(), float() lanza un ValueError para strings inválidos:

python
# invalid_float_conversion.py
# These work
print(float("3.14"))      # Output: 3.14
print(float("  2.5  "))   # Output: 2.5 (whitespace ignored)
print(float("-0.5"))      # Output: -0.5
print(float("inf"))       # Output: inf (infinity)
 
# These don't work
# print(float("hello"))   # Error: ValueError
# print(float("1.2.3"))   # Error: ValueError

Convertir booleanos a floats:

python
# bool_to_float.py
print(float(True))   # Output: 1.0
print(float(False))  # Output: 0.0

3.7.4) Convertir a string con str()

La función str() convierte cualquier valor a su representación como string:

Convertir números a strings:

python
# number_to_string.py
# Convert integer
age = 25
age_str = str(age)
print(age_str, type(age_str))  # Output: 25 <class 'str'>
 
# Convert float
price = 19.99
price_str = str(price)
print(price_str, type(price_str))  # Output: 19.99 <class 'str'>
 
# Now we can concatenate with other strings
message = "The price is $" + price_str
print(message)  # Output: The price is $19.99

Esto es particularmente útil al construir mensajes:

python
# building_messages.py
name = "Alice"
age = 25
height = 5.6
 
# Without str(), this would cause an error
# message = "Name: " + name + ", Age: " + age  # Error!
 
# With str(), it works
message = "Name: " + name + ", Age: " + str(age) + ", Height: " + str(height)
print(message)  # Output: Name: Alice, Age: 25, Height: 5.6

Convertir booleanos a strings:

python
# bool_to_string.py
is_valid = True
is_error = False
 
print(str(is_valid))  # Output: True
print(str(is_error))  # Output: False
 
# Useful in messages
status = "Status: " + str(is_valid)
print(status)  # Output: Status: True

Convertir None a string:

python
# none_to_string.py
value = None
value_str = str(value)
print(value_str)        # Output: None
print(type(value_str))  # Output: <class 'str'>
 
# The string "None" is different from the value None
print(value is None)      # Output: True
print(value_str is None)  # Output: False
print(value_str == "None")  # Output: True

3.7.5) Patrones de conversión en la práctica

Aquí tienes un ejemplo completo que muestra patrones comunes de conversión:

python
# conversion_patterns.py
# Get user input (always strings)
name = input("Enter your name: ")
age_str = input("Enter your age: ")
height_str = input("Enter your height in feet: ")
 
# Convert to appropriate types
age = int(age_str)
height = float(height_str)
 
# Perform calculations
age_in_months = age * 12
height_in_inches = height * 12
 
# Convert back to strings for output
print("Hello, " + name + "!")
print("You are " + str(age_in_months) + " months old.")
print("Your height is " + str(height_in_inches) + " inches.")
 
# Alternative: use multiple arguments to print() (no conversion needed)
print("Hello,", name + "!")
print("You are", age_in_months, "months old.")
print("Your height is", height_in_inches, "inches.")
 
# When user enters "Alice", "25", and "5.5":
# Output: Hello, Alice!
# Output: You are 300 months old.
# Output: Your height is 66.0 inches.
# Output: Hello, Alice!
# Output: You are 300 months old.
# Output: Your height is 66.0 inches.

Observa cómo print() con múltiples argumentos (separados por comas) convierte automáticamente los valores a strings y añade espacios entre ellos. Esto suele ser más cómodo que la conversión y concatenación manual de strings.

3.7.6) Diagrama de flujo de conversiones

Aquí tienes una representación visual de conversiones de tipos comunes:

float

int truncates

str

str

int

float

str

int

float

int

float

str

bool

Puntos clave sobre las conversiones:

  • int → float: Siempre seguro, añade .0
  • float → int: Trunca la parte decimal (no redondea)
  • Cualquier tipo → str: Siempre seguro, convierte a representación de texto
  • str → int/float: Solo funciona si el string representa un número válido
  • bool → int/float: True se convierte en 1/1.0, False en 0/0.0

3.7.7) Errores comunes de conversión

Aquí tienes algunos errores frecuentes que cometen los principiantes con la conversión de tipos:

Error 1: Olvidar convertir la entrada del usuario

python
# conversion_mistake1.py
# Wrong: trying to do math with string
age = input("Enter your age: ")
# next_year = age + 1  # Error: TypeError
 
# Right: convert first
age = int(input("Enter your age: "))
next_year = age + 1
print("Next year:", next_year)

Error 2: Convertir cuando no es necesario

python
# conversion_mistake2.py
# Unnecessary: print() handles conversion automatically
age = 25
print("Age:", age)  # This works fine
 
# No need for:
print("Age:", str(age))  # Unnecessary str() conversion

Error 3: Intentar convertir strings inválidos

python
# conversion_mistake3.py
# This will crash if user enters non-numeric input
# age = int(input("Enter your age: "))  # Crashes on "twenty"
 
# We'll learn to handle this safely in Chapter 27

Error 4: Esperar que int() redondee

python
# conversion_mistake4.py
# Wrong expectation: int() truncates, doesn't round
x = int(3.7)
print(x)  # Output: 3 (not 4!)
 
# If you want rounding, use round()
x = round(3.7)
print(x)  # Output: 4

3.8) Obtener representaciones de string con str() y repr()

3.8.1) La diferencia entre str() y repr()

Python proporciona dos formas de obtener una representación en string de un objeto: str() y repr(). Aunque puedan parecer similares, sirven a propósitos diferentes:

  • str(): Crea una representación de string "amigable", legible para humanos
  • repr(): Crea una representación de string "oficial", inequívoca, pensada para desarrolladores

Para tipos simples como números, a menudo son iguales, pero para otros tipos pueden diferir bastante:

python
# str_vs_repr.py
# For numbers, they're usually the same
x = 42
print(str(x))   # Output: 42
print(repr(x))  # Output: 42
 
# For strings, they differ
text = "Hello"
print(str(text))   # Output: Hello
print(repr(text))  # Output: 'Hello' (includes quotes!)
 
# For strings with special characters, repr() shows escape sequences
message = "Hello\nWorld"
print(str(message))   # Output: Hello
                      #         World (newline is interpreted)
print(repr(message))  # Output: 'Hello\nWorld' (shows the \n literally)

3.8.2) Cuándo usar str()

Usa str() cuando quieres una representación legible para usuarios finales:

python
# using_str.py
price = 19.99
quantity = 3
 
# Create user-friendly messages
message = "Total: $" + str(price * quantity)
print(message)  # Output: Total: $59.97
 
# str() is what print() uses automatically
print("Total: $", price * quantity)  # Output: Total: $ 59.97

La función str() está diseñada para producir salidas que tengan sentido para las personas, aunque pierdan algo de precisión técnica. Cuando llamas a print(), Python llama automáticamente a str() sobre los valores que le pasas.

3.8.3) Cuándo usar repr()

Usa repr() cuando necesitas una representación inequívoca, normalmente para depuración:

python
# using_repr.py
# Debugging: see exactly what's in a variable
text = "Hello\nWorld"
print("Debug info:", repr(text))  # Output: Debug info: 'Hello\nWorld'
 
# Compare two similar-looking strings
str1 = "42"
str2 = "42 "  # Has trailing space
 
print(str1)       # Output: 42
print(str2)       # Output: 42  (space not obvious)
print(repr(str1)) # Output: '42'
print(repr(str2)) # Output: '42 ' (space is visible!)

La función repr() está diseñada para mostrarte exactamente lo que ve Python, incluyendo detalles que podrían no ser visibles en una salida normal. Esto la hace muy valiosa para depurar.

3.8.4) El objetivo de repr(): representaciones recreables

Idealmente, repr() debería producir un string que, si lo pasaras al intérprete de Python, recrearía el objeto original. Para tipos básicos, esto funciona:

python
# repr_recreate.py
# For numbers
x = 42
x_repr = repr(x)
print(x_repr)  # Output: 42
 
# You could use this to recreate x
x_recreated = eval(x_repr)  # eval() evaluates a string as Python code
print(x_recreated)  # Output: 42
 
# For strings
text = "Hello"
text_repr = repr(text)
print(text_repr)  # Output: 'Hello'
 
# This could recreate the string
text_recreated = eval(text_repr)
print(text_recreated)  # Output: Hello

Nota importante: La función eval() evalúa un string como código Python. La mencionamos aquí para explicar el propósito de repr(), pero nunca uses eval() con entrada no confiable: es un riesgo de seguridad. Hablaremos de alternativas más seguras en capítulos posteriores.

3.8.5) Ejemplos prácticos de str() y repr()

Ejemplo 1: Depurar problemas con strings

python
# debugging_strings.py
# User input might have unexpected whitespace
user_input = "  Alice  "
 
print("User entered:", user_input)         # Output: User entered:   Alice  
print("Debug view:", repr(user_input))     # Output: Debug view: '  Alice  '
 
# Now the extra spaces are obvious!
cleaned = user_input.strip()  # Remove leading/trailing whitespace
print("Cleaned:", repr(cleaned))  # Output: Cleaned: 'Alice'

Ejemplo 2: Comparar distintos tipos

python
# comparing_types.py
# These look similar but are different
num = 42
text = "42"
 
print("Number:", num)       # Output: Number: 42
print("Text:", text)        # Output: Text: 42
 
print("Number repr:", repr(num))   # Output: Number repr: 42
print("Text repr:", repr(text))    # Output: Text repr: '42'
 
# repr() makes the difference clear
print("Are they equal?", num == text)  # Output: Are they equal? False

3.8.6) str() y repr() con otros tipos

Veamos cómo funcionan str() y repr() con los tipos que hemos aprendido:

python
# str_repr_types.py
# Integers
x = 42
print("int str:", str(x))    # Output: int str: 42
print("int repr:", repr(x))  # Output: int repr: 42
 
# Floats
y = 3.14159
print("float str:", str(y))   # Output: float str: 3.14159
print("float repr:", repr(y)) # Output: float repr: 3.14159
 
# Booleans
b = True
print("bool str:", str(b))   # Output: bool str: True
print("bool repr:", repr(b)) # Output: bool repr: True
 
# None
n = None
print("None str:", str(n))   # Output: None str: None
print("None repr:", repr(n)) # Output: None repr: None
 
# Strings (where they differ most)
s = "Hello\nWorld"
print("string str:", str(s))   # Output: string str: Hello
                                #                     World
print("string repr:", repr(s)) # Output: string repr: 'Hello\nWorld'

3.8.7) Ideas clave

Usa str() cuando:

  • Crees salida para usuarios finales
  • Construyas mensajes de cara al usuario
  • Formatees datos para mostrarlos
  • Quieras una salida legible y amistosa

Usa repr() cuando:

  • Depures código
  • Registres información técnica (logging)
  • Necesites ver exactamente qué hay en una variable
  • Quieras representaciones inequívocas

Recuerda:

  • print() usa automáticamente str() sobre sus argumentos
  • Para la mayoría de tipos básicos, str() y repr() dan resultados similares
  • Para strings, repr() incluye comillas y muestra secuencias de escape
  • repr() está diseñado para ser inequívoco y (idealmente) recreable

Resumen del capítulo

En este capítulo has aprendido los conceptos fundamentales de variables y tipos de datos en Python. Recapitulemos los puntos clave:

Variables:

  • Las variables son nombres que se refieren a valores en memoria
  • Se crean usando asignación: variable_name = value
  • Pueden reasignarse a nuevos valores en cualquier momento
  • Deben seguir reglas de nombrado y deberían seguir las convenciones
  • Usa nombres descriptivos para que el código se documente por sí mismo

Tipos de datos:

  • Cada valor en Python tiene un tipo
  • Usa type() para comprobar el tipo de un valor
  • Python es de tipado dinámico: las variables pueden referirse a distintos tipos en distintos momentos
  • Tipos distintos soportan operaciones distintas

Los tipos básicos:

  • int: Números enteros (positivos, negativos o cero), tamaño arbitrario
  • float: Números con punto decimal, pueden tener limitaciones de precisión
  • str: Texto entre comillas (simples o dobles)
  • bool: Valores lógicos True o False
  • None: Valor especial que representa ausencia de un valor

Conversión de tipos:

  • int(): Convierte a entero (trunca floats, analiza strings)
  • float(): Convierte a número de coma flotante
  • str(): Convierte a string (siempre funciona)
  • Las conversiones pueden fallar con entrada inválida (lanzan ValueError)

Representaciones de string:

  • str(): Representación legible para humanos y usuarios finales
  • repr(): Representación inequívoca para desarrolladores/depuración
  • print() usa str() automáticamente

Estos conceptos forman la base de todo lo demás en Python. Cada programa que escribas usará variables para almacenar datos, y entender los tipos de datos te ayuda a predecir qué operaciones funcionarán y qué errores podrían ocurrir.

En el próximo capítulo ampliaremos esta base explorando cómo trabajar con números en detalle, incluyendo operaciones aritméticas, precedencia de operadores y patrones numéricos comunes. Aprenderás a realizar cálculos, trabajar con funciones matemáticas y manejar las peculiaridades de la aritmética de coma flotante.

© 2025. Primesoft Co., Ltd.
support@primesoft.ai