Cómo crear y utilizar variables en Python correctamente

Cómo crear y utilizar variables en Python correctamente

Hace no mucho intenté explicarle a mi amigo humanista qué son las variables en programación. Tras quince minutos de analogías confusas con cajas, cajones y contenedores, me miró desconcertado y preguntó: «¿No hay alguna forma más sencilla?». En ese momento entendí que incluso los conceptos más básicos de programación requieren una explicación clara y estructurada, especialmente para quienes empiezan. De esa idea nació este artículo.

Si estás comenzando en la programación con Python, entender las variables es tu primer paso fundamental. Sin exagerar, es la base de la base, sin la cual no es posible avanzar. En esta guía cubriremos todo lo que necesitas saber sobre las variables en Python: desde ejemplos muy simples hasta matices que incluso desarrolladores experimentados encuentran.

¿Qué es una variable y para qué sirve?

Imagina que preparas un plato complejo siguiendo una receta. En vez de escribir siempre «250 gramos de harina», «2 cucharadas de azúcar» y así sucesivamente, sería más cómodo asignar nombres a esos ingredientes — «harina», «azúcar» — y luego usar esos nombres en la receta. Así funcionan las variables en programación.

Una variable en Python es una celda de memoria nombrada del ordenador que almacena un valor determinado. Ese valor puede ser un número, texto, lista, objeto o prácticamente cualquier otro tipo de dato. La característica principal de las variables es que, como su nombre indica, pueden cambiar su valor durante la ejecución del programa.

Aquí tienes el ejemplo más sencillo de creación de una variable en Python:


# Creamos la variable llamada message y le asignamos un valor
message = "¡Hola, mundo!"

# Usamos esa variable
print(message)  # Imprimirá: ¡Hola, mundo!

# Cambiamos el valor de la variable
message = "¡Bienvenido a Python!"

# Usamos la variable modificada
print(message)  # Imprimirá: ¡Bienvenido a Python!

A diferencia de muchos otros lenguajes de programación, en Python no es necesario declarar el tipo de la variable por adelantado: el intérprete lo determinará según el valor asignado. Esta característica hace a Python especialmente amigable para principiantes, permitiendo concentrarse en la lógica del programa y no en detalles técnicos.

Reglas de nomenclatura de variables: qué se puede y qué no

Cada lenguaje de programación tiene sus propias reglas para nombrar variables. Python no es una excepción. Aunque estas reglas son bastante flexibles, seguirlas es crucial para crear código legible y mantenible.

Reglas principales de nomenclatura de variables en Python:

  • El nombre de la variable puede contener solo letras (a-z, A-Z), dígitos (0-9) y el guion bajo (_).
  • El nombre no puede comenzar con un dígito.
  • El nombre no puede coincidir con palabras reservadas de Python (por ejemplo, if, else, while, for, class, def, etc.).
  • Python distingue mayúsculas de minúsculas, por lo que name, Name y NAME son tres variables distintas.

Además de las reglas formales, existen convenciones aceptadas que hacen el código más legible y comprensible:

  • Usa nombres significativos que describan el contenido de la variable (por ejemplo, user_name en vez de u o x).
  • Para variables normales utiliza snake_case — palabras en minúsculas separadas por guiones bajos (por ejemplo, first_name, items_count).
  • Los nombres de constantes (valores que no deberían cambiar) se escriben EN_MAYÚSCULAS_CON_GUIONES_BAJOS (por ejemplo, MAX_SIZE, API_KEY).
  • Evita nombres de una sola letra, salvo cuando su significado sea evidente por el contexto (por ejemplo, i en un bucle for).
  • No uses nombres que puedan entrar en conflicto con funciones integradas de Python (por ejemplo, no nombres variables list o str).

Aquí tienes ejemplos de nombres correctos e incorrectos:


# Nombres correctos
user_name = "Iván"
age = 25
item_1 = "Libro"
_private = "Variable interna"
MAXIMUM_ALLOWED = 100

# Nombres incorrectos
1variable = 10  # Error: el nombre no puede comenzar con un dígito
user-name = "Iván"  # Error: el guion no está permitido
class = "Python"  # Error: class — palabra reservada

Siempre aconsejo a los principiantes prestar especial atención a la nomenclatura de variables. Como decía uno de mis profesores de programación: «Un buen código debe leerse como un buen libro, no como un mensaje cifrado». Elegir bien los nombres de las variables es el primer paso hacia ese objetivo.

Tipos de datos en Python: qué puede almacenar una variable

Una de las nociones fundamentales en programación son los tipos de datos. El tipo de datos determina qué valores puede tomar una variable y qué operaciones se pueden realizar con esos valores. Python tiene un sistema de tipos amplio que incluye tipos simples (primitivos) y complejos (compuestos).

Veamos los tipos de datos principales que encontrarás en Python:

Tipos numéricos: int, float, complex

Python soporta tres tipos numéricos:

  • int (enteros) — números sin parte decimal, por ejemplo: 5, -10, 1000.
  • float (coma flotante) — números con parte decimal, por ejemplo: 3.14, -0.5, 2.0.
  • complex (números complejos) — números con parte real e imaginaria, por ejemplo: 3+4j, 2-1j.

# Ejemplos de tipos numéricos
count = 42  # int
price = 19.99  # float
complex_number = 3 + 4j  # complex

# Operaciones con números
sum_result = count + 10  # 52
product = price * 2  # 39.98

Curiosidad: en Python los enteros (int) no tienen límite de tamaño, salvo la memoria disponible. Esto significa que puedes trabajar con números muy grandes sin bibliotecas especiales.

Strings (str)

Las cadenas son secuencias de caracteres entre comillas simples ('texto') o dobles ("texto"). En Python las cadenas son inmutables (immutable), es decir, una vez creada una cadena no se puede modificar.


# Creación de cadenas
name = "Ana"
message = '¡Hola, mundo!'
multi_line = """Esta es una
cadena multilínea en Python. Puede abarcar varias líneas."""

# Operaciones con cadenas
greeting = "Hola, " + name + "!"  # Concatenación: "Hola, Ana!"
repeated = "Python " * 3  # Repetición: "Python Python Python "
length = len(name)  # Longitud de la cadena: 3

Python ofrece muchos métodos integrados para trabajar con cadenas, como upper(), lower(), strip(), replace(), split() y muchos otros. Esto hace que el procesamiento de texto en Python sea muy cómodo.

Tipo booleano (bool)

Las variables booleanas solo pueden tomar dos valores: True (verdadero) o False (falso). El tipo booleano se usa frecuentemente en expresiones condicionales y bucles.


# Ejemplos de variables booleanas
is_active = True
has_permission = False

# Operaciones lógicas
is_eligible = is_active and has_permission  # False
can_proceed = is_active or has_permission  # True
is_inactive = not is_active  # False

En Python muchos valores se convierten automáticamente a bool en un contexto lógico. Por ejemplo, cadenas vacías, números cero, None y secuencias vacías se consideran False, y los valores no vacíos se consideran True.

Listas (list)

Una lista es una colección ordenada de elementos que pueden ser de distintos tipos. Las listas en Python son mutables (mutable), es decir, se puede añadir, eliminar o modificar elementos tras crear la lista.


# Creación de lista
fruits = ["manzana", "banana", "naranja"]
mixed_list = [1, "texto", True, 3.14]

# Acceso a elementos de la lista (indexación desde 0)
first_fruit = fruits[0]  # "manzana"
last_fruit = fruits[-1]  # "naranja"

# Modificar un elemento de la lista
fruits[1] = "pera"  # Ahora la lista: ["manzana", "pera", "naranja"]

# Añadir elemento al final de la lista
fruits.append("mango")  # Ahora la lista: ["manzana", "pera", "naranja", "mango"]

# Eliminar elemento
fruits.remove("pera")  # Ahora la lista: ["manzana", "naranja", "mango"]

# Longitud de la lista
count = len(fruits)  # 3

Las listas son uno de los tipos de datos más flexibles y usados en Python. Permiten almacenar y procesar colecciones de objetos de forma eficiente.

Tuplas (tuple)

Una tupla, al igual que una lista, es una colección ordenada de elementos, pero a diferencia de la lista la tupla es inmutable (immutable). Tras crear una tupla no se pueden añadir, eliminar o modificar sus elementos.


# Creación de tupla
coordinates = (10, 20)
person = ("Iván", 30, "Programador")

# Acceso a elementos de la tupla
x = coordinates[0]  # 10
name = person[0]  # "Iván"

# Desempaquetado de tupla
name, age, profession = person  # name = "Iván", age = 30, profession = "Programador"

# Intentar modificar la tupla provocará un error
# coordinates[0] = 15  # TypeError: 'tuple' object does not support item assignment

Las tuplas se usan a menudo cuando se necesita inmutabilidad, por ejemplo, como claves en diccionarios o para devolver varios valores desde una función.

Diccionarios (dict)

Un diccionario es una colección no ordenada de pares "clave-valor". Las claves deben ser únicas e inmutables (normalmente cadenas o números), y los valores pueden ser de cualquier tipo.


# Creación de diccionario
person = {
    "name": "María",
    "age": 28,
    "city": "Moscú"
}

# Acceso a valores por clave
name = person["name"]  # "María"

# Modificar un valor
person["age"] = 29  # Ahora age = 29

# Añadir un nuevo par clave-valor
person["email"] = "maria@example.com"

# Eliminar un par clave-valor
del person["city"]

# Comprobar existencia de una clave
has_email = "email" in person  # True

Los diccionarios son un tipo de dato extremadamente útil que permite modelar muchas estructuras reales, como perfiles de usuario, configuraciones, tablas de correspondencia, etc.

Conjuntos (set)

Un conjunto es una colección no ordenada de elementos únicos. Los conjuntos se usan cuando importa la existencia de un elemento, no su posición ni la cantidad de repeticiones.


# Creación de conjunto
colors = {"rojo", "verde", "azul"}
numbers = set([1, 2, 2, 3, 3, 3])  # Creación desde lista con duplicados, resultado: {1, 2, 3}

# Añadir elemento
colors.add("amarillo")

# Eliminar elemento
colors.remove("verde")

# Operaciones con conjuntos
set1 = {1, 2, 3}
set2 = {3, 4, 5}
union = set1 | set2  # Unión: {1, 2, 3, 4, 5}
intersection = set1 & set2  # Intersección: {3}
difference = set1 - set2  # Diferencia: {1, 2}

Los conjuntos son especialmente útiles para eliminar duplicados de secuencias y para realizar operaciones matemáticas con colecciones.

None — ausencia de valor

None es un valor especial en Python que representa la ausencia de valor. Se usa a menudo como valor por defecto para parámetros opcionales de funciones o para indicar que no hay resultado.


# Uso de None
result = None
# ... alguna lógica ... if condition:
    result = calculate_something()

# Comprobación de None
if result is None:
    print("Resultado no encontrado")

Al trabajar con None es importante usar los operadores is e is not, en vez de == y !=, para comparar, ya que es la forma más precisa de verificar identidad de objetos.

Asignación y modificación de variables

En Python la asignación de un valor a una variable se hace con el operador =. Este proceso parece simple, pero encierra varias ideas importantes que hay que comprender.

Asignación básica

La forma más sencilla de asignar un valor a una variable:


# Asignación de valor a variable
x = 10
name = "Alexéi"
is_valid = True

En Python una variable es simplemente un nombre que referencia a un objeto en memoria. Cuando asignas un valor a una variable creas la relación entre el nombre de la variable y el objeto.

Asignación múltiple

Python permite asignar valores a varias variables en una sola línea:


# Asignar un mismo valor a varias variables
x = y = z = 0  # x, y y z valen 0

# Asignar valores distintos a varias variables
a, b, c = 1, 2, 3  # a = 1, b = 2, c = 3

# Desempaquetado de una secuencia
coordinates = (10, 20, 30)
x, y, z = coordinates  # x = 10, y = 20, z = 30

La asignación múltiple hace el código más compacto y legible, especialmente al trabajar con tuplas y listas.

Asignación compuesta

Python ofrece operadores compuestos que combinan la operación y la asignación:


# Operadores compuestos de asignación
x = 10
x += 5  # Equivalente a x = x + 5, ahora x = 15
x -= 3  # Equivalente a x = x - 3, ahora x = 12
x *= 2  # Equivalente a x = x * 2, ahora x = 24
x /= 4  # Equivalente a x = x / 4, ahora x = 6.0 (observe la conversión a float)

# Los operadores compuestos no solo funcionan con números
text = "Hello"
text += " World"  # Concatenación: "Hello World"

numbers = [1, 2]
numbers += [3, 4]  # Extensión de la lista: [1, 2, 3, 4]

Los operadores compuestos no solo acortan el código, sino que suelen ser más eficientes, ya que pueden realizar la operación "in situ" sin crear objetos intermedios.

Tipos mutables e inmutables

Entender la diferencia entre tipos mutables y inmutables es clave para trabajar con variables en Python:

  • Tipos inmutables: int, float, bool, str, tuple, frozenset. Tras crear objetos de estos tipos no se pueden modificar. Cualquier operación que parezca "modificarlos" crea un nuevo objeto.
  • Tipos mutables: list, dict, set. Los objetos de estos tipos sí se pueden modificar tras su creación, sin crear un objeto nuevo.

Esta distinción afecta al comportamiento de las variables al asignarlas y al pasarlas a funciones:


# Tipo inmutable (int)
a = 10
b = a  # b y a referencian al mismo objeto
a = 20  # Se crea un nuevo objeto, a ahora referencia a él
print(b)  # 10, b sigue referenciando el objeto original

# Tipo mutable (list)
x = [1, 2, 3]
y = x  # y y x referencian a la misma lista
x.append(4)  # Modificamos la lista a través de x
print(y)  # [1, 2, 3, 4], los cambios se ven a través de y, ya que es el mismo objeto

Cuando empecé con Python esta diferencia me confundía constantemente. Recuerdo pasar horas depurando una función que modificaba inesperadamente la lista de entrada: no tuve en cuenta que estaba pasando un objeto mutable por referencia.

Ámbito de las variables: dónde y cuándo está disponible una variable

El ámbito (scope) determina dónde en el programa puedes usar una variable. Entender los ámbitos ayuda a evitar errores inesperados y conflictos de nombres.

En Python existen varios niveles de ámbito:

Ámbito local

Las variables definidas dentro de una función tienen ámbito local. Están disponibles solo dentro de esa función y existen únicamente mientras se ejecuta.


def calculate_total(price, quantity):
    # Variables locales price, quantity y total
    total = price * quantity
    return total

result = calculate_total(10, 5)  # 50
# print(total)  # Error: la variable total no está definida fuera de la función

Ámbito global

Las variables definidas en el nivel superior del módulo (fuera de funciones y clases) tienen ámbito global. Están disponibles en cualquier parte del módulo, incluso dentro de funciones.


# Variable global
app_name = "MyApp"

def print_app_info():
    # Lectura de la variable global dentro de la función
    print(f"Nombre de la aplicación: {app_name}")

print_app_info()  # Imprimirá: Nombre de la aplicación: MyApp

Sin embargo, si intentas modificar una variable global dentro de una función, Python creará una variable local con el mismo nombre en lugar de modificar la global. Para cambiar una variable global hay que usar la palabra clave global:


counter = 0

def increment_counter():
    global counter  # Indicamos que queremos usar la variable global
    counter += 1
    return counter

print(increment_counter())  # 1
print(counter)  # 1 - la variable global cambió

Ámbito nonlocal (encerrante)

En funciones anidadas existe un ámbito intermedio entre el local y el global: el ámbito de cierre (enclosing). La palabra clave nonlocal permite modificar variables de la función externa.


def create_counter():
    count = 0
    
    def increment():
        nonlocal count  # Usamos la variable de la función externa
        count += 1
        return count
    
    return increment

counter = create_counter()
print(counter())  # 1
print(counter())  # 2
print(counter())  # 3

Este ejemplo muestra la poderosa idea de closures en Python, donde la función interna "recuerda" variables de su ámbito externo.

Orden de búsqueda de variables (LEGB)

Python busca variables en un orden determinado, conocido por la regla LEGB:

  1. Local: dentro de la función actual
  2. Enclosing: en funciones externas
  3. Global: a nivel de módulo
  4. Built-in: nombres integrados de Python (print, len, etc.)

x = "global"  # Variable global

def outer():
    x = "enclosing"  # Variable del ámbito encerrante
    
    def inner():
        x = "local"  # Variable local
        print(x)
    
    inner()
    print(x)

outer()
print(x)

# Salida:
# local
# enclosing
# global

Comprender este orden de búsqueda ayuda a predecir qué valor se usará al referirse a una variable en distintos puntos del programa.

Variables globales: pros y contras

Las variables globales están disponibles en todo el programa, lo que las hace convenientes para almacenar datos que se necesitan en muchos sitios. Sin embargo, usar variables globales tiene ventajas y desventajas importantes.

Ventajas de las variables globales

  • Disponibilidad desde cualquier parte del programa sin necesidad de pasar valores mediante parámetros.
  • Útiles para almacenar constantes y configuraciones de la aplicación.
  • Permiten intercambio de datos entre funciones sin pasar explícitamente valores.

Desventajas de las variables globales

  • Dificultan la comprensión del código, ya que no queda claro qué funciones modifican las variables globales.
  • Complican las pruebas y la depuración, porque el estado del programa puede cambiar de forma implícita.
  • Pueden llevar a comportamientos impredecibles en ejecución paralela.
  • Crean acoplamientos fuertes entre partes del programa, lo que dificulta la reutilización del código.

Como regla general, la mayoría de desarrolladores experimentados en Python recomiendan evitar variables globales mutables, salvo cuando son realmente necesarias. En su lugar es mejor usar:

  • Pasar argumentos a funciones
  • Devolver valores desde funciones
  • Clases para almacenar estado relacionado
  • Módulos para organizar configuraciones y constantes

Aquí hay un ejemplo de mejora de código que usa variables globales:


# Mala práctica: uso de variables globales
total_score = 0
player_name = ""

def set_player_name(name):
    global player_name
    player_name = name

def add_points(points):
    global total_score
    total_score += points

def get_score():
    return f"{player_name}: {total_score}"

# Mejor práctica: uso de una clase
class Player:
    def __init__(self, name):
        self.name = name
        self.score = 0
    
    def add_points(self, points):
        self.score += points
    
    def get_score(self):
        return f"{self.name}: {self.score}"

# Uso
player = Player("Jugador 1")
player.add_points(10)
print(player.get_score())  # "Jugador 1: 10"

La segunda versión es mejor porque encapsula datos y métodos relacionados en un único objeto, hace explícitas las dependencias y permite crear varias instancias de Player si es necesario.

Constantes en Python: ¿existen?

A diferencia de muchos otros lenguajes, Python no tiene un mecanismo incorporado para crear verdaderas constantes — variables cuyo valor no puede cambiar tras la inicialización. No obstante, existen convenciones y técnicas que ayudan a emular constantes.

Convención de nomenclatura para constantes

Por convención, las constantes en Python se nombran EN_MAYÚSCULAS_CON_GUIONES_BAJOS. Esto indica a otros desarrolladores que esas variables no deberían modificarse, aunque técnicamente nada impide cambiar su valor.


# Constantes por convención
MAX_CONNECTIONS = 100
API_KEY = "abc123"
DEFAULT_TIMEOUT = 30

Estas "constantes" normalmente se definen a nivel de módulo y se importan en otros módulos cuando es necesario.

Uso de módulos para constantes

Es buena práctica definir todas las constantes en un módulo aparte, por ejemplo constants.py:


# constants.py
DATABASE_URL = "postgresql://user:password@localhost/db"
MAX_USERS = 1000
DEBUG_MODE = False

Luego estas constantes se pueden importar desde otros módulos:


# En otros archivos
from constants import DATABASE_URL, MAX_USERS

# Uso
if user_count > MAX_USERS:
    print("Se ha superado el número máximo de usuarios")

Este enfoque centraliza la configuración de la aplicación y facilita su modificación.

Creación de objetos inmutables

Para crear constantes realmente inmutables se pueden usar descriptores de propiedades o heredar de tipos inmutables. Aquí hay un ejemplo con una clase y propiedades:


class Constants:
    def __init__(self):
        self._MAX_SIZE = 100
        self._API_VERSION = "v1"
    
    @property
    def MAX_SIZE(self):
        return self._MAX_SIZE
    
    @property
    def API_VERSION(self):
        return self._API_VERSION

# Uso
constants = Constants()
print(constants.MAX_SIZE)  # 100
# constants.MAX_SIZE = 200  # Provocará AttributeError

Este enfoque ofrece cierta protección frente a cambios accidentales de constantes, aunque un desarrollador experimentado aún podría modificar el estado interno del objeto constants.

Uso de namedtuple

Otra forma de crear constantes inmutables es usar namedtuple del módulo collections:


from collections import namedtuple

Constants = namedtuple('Constants', ['MAX_SIZE', 'API_VERSION'])
const = Constants(MAX_SIZE=100, API_VERSION='v1')

print(const.MAX_SIZE)  # 100
# const.MAX_SIZE = 200  # Provocará AttributeError, ya que namedtuple es inmutable

Este enfoque proporciona una garantía de inmutabilidad más estricta que la simple convención de nombres.

A pesar de la ausencia de un mecanismo nativo para constantes, usar estas técnicas ayuda a crear código más predecible y mantenible, dejando claro que ciertos valores no deben cambiar.

Desempaquetado de variables: el Python elegante

El desempaquetado de variables (unpacking) es una característica elegante de Python que permite asignar valores a múltiples variables desde un objeto iterable (lista, tupla, cadena, etc.) en una sola operación. Esta posibilidad hace el código más conciso y legible.

Desempaquetado básico

El ejemplo más simple de desempaquetado es asignar elementos de una secuencia a variables separadas:


# Desempaquetado de tupla
coordinates = (10, 20, 30)
x, y, z = coordinates  # x = 10, y = 20, z = 30

# Desempaquetado de lista
rgb = [255, 128, 0]
red, green, blue = rgb  # red = 255, green = 128, blue = 0

# Desempaquetado de cadena
a, b, c = "XYZ"  # a = 'X', b = 'Y', c = 'Z'

Es importante que el número de variables a la izquierda del operador = coincida exactamente con el número de elementos de la secuencia, de lo contrario Python lanzará un ValueError.

Desempaquetado ignorando valores

Si solo necesitas algunos valores de la secuencia, puedes usar el guion bajo (_) para ignorar los valores no deseados:


# Extraer solo el primer y el último elemento
data = [1, 2, 3, 4, 5]
first, *_, last = data  # first = 1, last = 5

# Extraer solo el segundo elemento
_, second, *_ = data  # second = 2

El guion bajo es una variable normal en Python, pero por convención se usa para valores que no se van a utilizar.

Desempaquetado con el operador *

El operador * permite agrupar varios elementos en una lista. Es muy útil cuando la cantidad de elementos de la secuencia es desconocida:


# Desempaquetado con *
first, *rest = [1, 2, 3, 4, 5]  # first = 1, rest = [2, 3, 4, 5]

*beginning, last = [1, 2, 3, 4, 5]  # beginning = [1, 2, 3, 4], last = 5

first, *middle, last = [1, 2, 3, 4, 5]  # first = 1, middle = [2, 3, 4], last = 5

En una misma expresión de desempaquetado solo puede haber un operador *.

Desempaquetado de diccionarios

El desempaquetado también funciona con diccionarios, permitiendo extraer claves, valores o pares clave-valor:


# Desempaquetado de diccionario
person = {"name": "Ana", "age": 25, "city": "Moscú"}

# Desempaquetado de claves
a, b, c = person  # a = 'name', b = 'age', c = 'city'

# Desempaquetado de valores
a, b, c = person.values()  # a = 'Ana', b = 25, c = 'Moscú'

# Desempaquetado de pares clave-valor
a, b, c = person.items()  # a = ('name', 'Ana'), b = ('age', 25), c = ('city', 'Moscú')

Ejemplos prácticos de desempaquetado

El desempaquetado hace el código más elegante en muchas situaciones:


# Intercambio de valores sin variable temporal
a, b = 10, 20
a, b = b, a  # Ahora a = 20, b = 10

# Devolver varios valores desde una función
def get_user_info():
    return "Alexéi", 30, "alex@example.com"

name, age, email = get_user_info()

# Desempaquetado en un bucle for
points = [(1, 2), (3, 4), (5, 6)]
for x, y in points:
    print(f"X: {x}, Y: {y}")

# Desempaquetado al analizar datos estructurados
data = [("Manzana", 5, 0.5), ("Banana", 3, 0.3), ("Naranja", 2, 0.4)]
for fruit, quantity, price in data:
    total = quantity * price
    print(f"{fruit}: {quantity} uds. × {price} = {total}")

El desempaquetado es una de esas características de Python que hacen el lenguaje más expresivo y cómodo. Usarlo con habilidad ayuda a escribir código más limpio y comprensible, evitando variables temporales y líneas innecesarias.

Errores comunes al trabajar con variables

Incluso programadores experimentados cometen errores al trabajar con variables. Veamos los problemas más comunes y cómo evitarlos.

Usar una variable antes de definirla

Uno de los errores más comunes es intentar usar una variable antes de que haya sido definida:


# Error: referencia a variable indefinida
print(x)  # NameError: name 'x' is not defined
x = 10

Python ejecuta el código de forma secuencial, línea por línea, por lo que la variable debe definirse antes de usarse.

Errores tipográficos en nombres de variables

Python distingue mayúsculas y minúsculas, y los errores tipográficos en nombres de variables son una causa frecuente de fallos:


# Error: error tipográfico en el nombre de la variable
user_name = "Ana"
print(userName)  # NameError: name 'userName' is not defined

Solución: usa un buen editor de código con resaltado de sintaxis y autocompletado que ayude a evitar estos errores.

Ocultar funciones y módulos integrados

A veces los programadores sobrescriben por accidente funciones o módulos integrados de Python, lo que provoca errores inesperados:


# Error: sobrescribir una función integrada
list = [1, 2, 3]  # Ahora list es una variable, no la función
new_list = list([4, 5, 6])  # TypeError: 'list' object is not callable

Solución: evita usar nombres que coincidan con funciones y tipos integrados de Python, como list, dict, str, int, sum, max, etc.

Uso incorrecto de variables globales

Intentar modificar una variable global dentro de una función sin la palabra clave global conduce a la creación de una nueva variable local:


counter = 0

def increment():
    counter += 1  # UnboundLocalError: local variable 'counter' referenced before assignment
    return counter

# Variante correcta
def increment_correct():
    global counter
    counter += 1
    return counter

Solución: usa global o nonlocal cuando necesites modificar una variable de un ámbito externo.

Problemas con objetos mutables como valores por defecto

Usar objetos mutables (listas, diccionarios) como valores por defecto de parámetros puede provocar comportamientos inesperados:


# Error: usar un objeto mutable como valor por defecto
def add_item(item, items=[]):
    items.append(item)
    return items

print(add_item("manzana"))  # ["manzana"]
print(add_item("banana"))   # ["manzana", "banana"] — ¡inesperado!

# Variante correcta
def add_item_correct(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

En Python los valores por defecto se evalúan solo una vez al definir la función, no en cada llamada. Por tanto, si modificas ese valor por defecto dentro de la función, los cambios persisten entre llamadas.

Confusión con referencias a objetos

La comprensión incorrecta de cómo funcionan las referencias en Python, especialmente al copiar objetos mutables, produce errores:


# Error: modificación inesperada del objeto
original = [1, 2, [3, 4]]
copy = original  # Esto no crea una copia, solo una nueva referencia al mismo objeto
copy[2][0] = 30  # Modifica la lista anidada
print(original)  # [1, 2, [30, 4]] — ¡original también cambió!

# Formas correctas de copiar
import copy
shallow_copy = original.copy()  # o list(original), o original[:]
deep_copy = copy.deepcopy(original)  # Crea una copia completa, incluyendo objetos anidados

Solución: entiende la diferencia entre copia superficial (shallow) y copia profunda (deep) y usa el método apropiado según la situación.

Ten cuidado con estos errores comunes y podrás escribir código Python más fiable y predecible. Recuerda que comprender conceptos básicos como ámbitos, mutabilidad y el modelo de referencias te ayudará a evitar muchos problemas.

Buenas prácticas al trabajar con variables en Python

A lo largo de los años la comunidad Python ha desarrollado un conjunto de convenciones y recomendaciones que ayudan a escribir código más limpio, legible y mantenible. Aquí están las prácticas clave que conviene aplicar al trabajar con variables.

Nombres de variables significativos

Elige nombres que describan claramente el propósito de la variable:

  • Usa nombres descriptivos en lugar de letras sueltas (excepciones: i, j, k para índices; x, y, z para coordenadas).
  • Sigue la convención snake_case para nombres de variables y funciones (palabras en minúsculas separadas por guiones bajos).
  • Los nombres no deben ser demasiado largos ni demasiado cortos: busca un equilibrio entre brevedad y claridad.

# Mal
x = 100
tmp = "John Doe"
lst = ["apple", "banana", "orange"]

# Bien
max_attempts = 100
user_full_name = "John Doe"
fruits = ["apple", "banana", "orange"]

Agrupar variables relacionadas

Hay varias formas de agrupar variables relacionadas:

  • Para constantes relacionadas usa diccionarios o módulos.
  • Para estado relacionado usa clases.
  • Para configuración usa objetos de configuración.

# Agrupar constantes en un diccionario
CONFIG = {
    "MAX_USERS": 100,
    "DEFAULT_TIMEOUT": 30,
    "API_URL": "https://api.example.com"
}

# Agrupar estado relacionado en una clase
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email
        self.active = True
        self.last_login = None

Limitar el ámbito de las variables

Procura limitar el ámbito de las variables al nivel mínimo necesario:

  • Define variables en el ámbito más estrecho donde se usan.
  • Evita variables globales cuando sea posible.
  • Pasa valores mediante parámetros y valores de retorno.

# Mal: uso de variable global
total = 0

def add_to_total(value):
    global total
    total += value

# Bien: pasar valores mediante parámetros y retorno
def add_to_total(current_total, value):
    return current_total + value

total = 0
total = add_to_total(total, 10)

Convenciones de nombres para casos especiales

Usa convenciones aceptadas para casos especiales:

  • MAYÚSCULAS_PARA_CONSTANTES (MAX_SIZE, API_KEY).
  • Guion bajo al inicio (_variable) para variables "internas".
  • Doble guion bajo al inicio (__variable) para atributos privados de clase.
  • Guion bajo único (_) para variables temporales o no usadas.

# Constante
MAX_CONNECTIONS = 100

# Variable "interna" del módulo
_cache = {}

class User:
    def __init__(self, name):
        self.name = name
        self.__password = None  # Atributo privado

# Variable no utilizada en un bucle
for _ in range(5):
    print("Hello")

Inicializar variables antes de usarlas

Inicializa siempre las variables antes de usarlas para evitar errores y hacer el código más claro:


# Mal: la variable puede no estar definida
def process_data(data):
    if data:
        result = perform_calculation(data)
    # result puede no estar definida si data está vacío
    return result

# Bien: la variable siempre está definida
def process_data(data):
    result = None  # Inicialización con valor por defecto
    if data:
        result = perform_calculation(data)
    return result

Usa enumeraciones para constantes relacionadas

Para constantes relacionadas, especialmente si representan un conjunto de valores posibles, usa Enum del módulo enum:


from enum import Enum, auto

class Color(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

# Uso
def paint(color):
    if color == Color.RED:
        print("Pintamos de rojo")
    elif color == Color.GREEN:
        print("Pintamos de verde")
    elif color == Color.BLUE:
        print("Pintamos de azul")

paint(Color.RED)

Esto mejora la tipificación, el autocompletado en IDEs y protege frente a errores tipográficos respecto al uso de cadenas o números simples.

Usa anotaciones de tipo

Desde Python 3.5 se pueden usar anotaciones de tipo para indicar los tipos esperados de variables y parámetros de funciones:


def calculate_total(price: float, quantity: int) -> float:
    return price * quantity

user_name: str = "Ana"
scores: list[int] = [95, 87, 92]

Las anotaciones no afectan la ejecución del programa, pero ayudan a herramientas de análisis estático (por ejemplo, mypy) a detectar errores potenciales y mejoran la documentación.

Siguiendo estas prácticas escribirás código que no solo funcione, sino que sea fácil de leer, mantener y ampliar por otros desarrolladores —incluyéndote a ti mismo meses después de escribirlo.

Conclusión: de lo simple a lo complejo

Hemos recorrido un largo camino —desde la comprensión básica de las variables hasta las sutilezas de su uso, desde ejemplos simples hasta prácticas eficaces. Las variables en Python pueden parecer un concepto sencillo a primera vista, pero, como hemos visto, detrás de esa sencillez hay muchos matices y capacidades potentes.

Puntos clave para recordar:

  • Las variables en Python son nombres que apuntan a objetos en memoria.
  • Python es un lenguaje de tipado dinámico que determina el tipo de variable según el valor asignado.
  • Elegir nombres significativos para las variables es crucial para crear código comprensible.
  • Entender los ámbitos y el ciclo de vida de las variables ayuda a evitar muchos errores comunes.
  • La diferencia entre tipos mutables e inmutables afecta el comportamiento de las variables al asignarlas y pasarlas a funciones.
  • Python ofrece características elegantes, como el desempaquetado, que hacen el código más conciso y expresivo.
  • Seguir las buenas prácticas al trabajar con variables mejora la calidad del código y facilita su mantenimiento.

Para mí, entender las variables fue el primer paso desde escribir scripts sencillos hasta crear programas reales. Tal vez me entusiasme demasiado, pero creo que hay algo mágico en cómo unas pocas líneas de código pueden dar vida a un ordenador y hacer que resuelva problemas reales.

No temas experimentar con lo que has aprendido. Crea tus propios programas, comete errores y aprende de ellos. Cada error es una oportunidad para profundizar tu comprensión.

Y lo más importante: recuerda que incluso los programadores experimentados siguen aprendiendo. Python evoluciona, aparecen nuevas características y prácticas. Mantente curioso, haz preguntas y sigue explorando este lenguaje fascinante.

Espero que esta guía te ayude a dar los primeros pasos con confianza en el mundo de Python y que te proporcione una base sólida para seguir aprendiendo. ¡Buena suerte en tu viaje por la programación!

Alt text