Skip to main content

Declaración de variables en Python

Python permite escribir programas de forma muy libre: puedes declarar variables sin tipos, cambiar sus valores o incluso su tipo en cualquier momento. Esta flexibilidad hace que el lenguaje sea ideal para tareas exploratorias, prototipado y enseñanza inicial. Sin embargo, cuando el objetivo es construir bibliotecas reutilizables y mantenibles, esa misma libertad plantea nuevos desafíos.

En esta lección aprenderás cómo se declaran y manipulan variables en Python, y cómo implementar propiedades con lógica de acceso mediante decoradores. También analizaremos en qué se diferencia este modelo del enfoque de Kotlin —más estructurado y expresivo— y qué herramientas del ecosistema pueden ayudarte a recuperar parte de esa expresividad en tus diseños.

Al finalizar, contarás con una base sólida para decidir cuándo y cómo usar las herramientas de Python de forma responsable, entendiendo los beneficios de su flexibilidad y los riesgos de su falta de restricciones.

🐍 Variables en Python

A diferencia de Kotlin, Python no exige declarar el tipo de una variable ni usar palabras clave como val o var.
Simplemente se asigna un valor a un nombre, y el tipo se deduce automáticamente en tiempo de ejecución.

Variables en Python
name = "Emilia"
mana = 80

Esta flexibilidad hace que Python sea más sencillo para principiantes, pero también puede esconder errores que en Kotlin serían detectados en tiempo de compilación.

🔄 Reasignación libre (mutabilidad de referencia)

En Python, puedes reasignar una variable en cualquier momento, sin importar el tipo de dato:

Reasignación de variables
mana = 100
mana = 75 # ✅ Reasignación válida

Esto contrasta con Kotlin, donde puedes declarar una variable como inmutable usando val, lo que impide cambiar su referencia.

🚫 Inmutabilidad por convención

Python no ofrece una forma nativa de declarar variables inmutables como val en Kotlin.
Sin embargo, existen algunas convenciones que ayudan a simular constantes:

✅ Usar mayúsculas por convención

Convención de constantes
MAX_MANA = 100

Esta es una convención común en Python para indicar que un valor no debería cambiarse, aunque nada impide modificarlo.

🔒 Inmutabilidad con Final (Python 3.8+)

Desde Python 3.8, puedes usar Final del módulo typing para declarar que una variable no debe ser reasignada.

Declarar una variable inmutable con Final
from typing import Final

SPIRIT_NAME: Final[str] = "Puck"

Aunque Final no impide la reasignación en tiempo de ejecución, herramientas de análisis estático como mypy pueden detectar usos incorrectos:

Error detectado por mypy
SPIRIT_NAME = "Muspel"  # ⚠️ mypy: Cannot assign to final variable "SPIRIT_NAME"

Buenas prácticas

Si estás desarrollando bibliotecas o trabajando en proyectos colaborativos, usar Final es una forma explícita de comunicar la intención de inmutabilidad.
Aunque no impide errores en tiempo de ejecución, ayuda a prevenirlos de forma anticipada gracias a herramientas como mypy o Pyright.

🧱 Propiedades con decoradores

A diferencia de Kotlin, donde todas las variables son propiedades (ya sea dentro o fuera de una clase), en Python solo puedes declarar propiedades dentro de clases y debes definirlas explícitamente con métodos especiales.

Sintaxis de una propiedad en Python (suponiendo que existe el tipo T)
class Foo:
__value: T

@property
def value(self) -> T: ...

@value.setter
def value(self, value: T) -> None: ...

@value.deleter
def value(self) -> None: ...

📚 Ejemplo práctico: Exponer una lista como inmutable

Supón que estás desarrollando una clase Author y deseas que otras personas puedan consultar las obras del autor, pero sin poder modificarlas directamente.

type-fundamentals/basics/variables/author.py
class Author:
__name: str
__works: list[str]

def __init__(self, name: str, works: list[str]):
self.__name = name
self.__works = works

@property
def works(self) -> tuple[str, ...]:
return tuple(self.__works)

✏️ Ejemplo práctico: Validar y controlar una propiedad editable

Supón que estás creando una clase User y quieres permitir la lectura y edición del nombre, pero validando que no esté vacío. Además, quieres poder eliminar el nombre si es necesario.

type-fundamentals/basics/variables/user.py
class User:
__name: str

def __init__(self, name: str):
self.__name = name

@property
def name(self) -> str:
return self.__name

@name.setter
def name(self, value: str) -> None:
if not value.strip():
raise ValueError("Name cannot be empty")
self.__name = value

@name.deleter
def name(self) -> None:
self.__name = "Anonymous"

🆚 Resumen comparativo

AspectoKotlinPython
DeclaraciónRequiere val o var y especificar tipo (opcional con inferencia).Asignación directa sin palabra clave ni tipo declarado.
Mutabilidadval (inmutable) y var (mutable).Todas las variables son mutables por defecto.
Control de mutabilidadLa referencia puede ser inmutable (val), pero el contenido puede ser mutable.La mutabilidad depende del tipo del objeto (int inmutable, list mutable).
Constantesval para referencias constantes, const val para constantes en tiempo de compilación.No hay constantes reales; se usa convención (MAYÚSCULAS) o Final (desde Python 3.8).
Propiedades (dentro de clases)Toda propiedad puede tener get/set personalizados con acceso controlado.Uso explícito de decoradores @property, @setter y @deleter.
Visibilidad del setterPuede limitarse (ej. private set).No hay modificadores de acceso; se controla indirectamente con convención o encapsulación.
Campos de respaldo / backing fieldsUsa field para acceder al valor real en get/set.Se accede directamente a atributos privados (ej. __name) dentro de métodos.
Vista inmutable de estructuras mutablesExponer List<T> desde MutableList<T> (conversión implícita).Exponer tuple desde list para garantizar inmutabilidad.
Validación en settersSe usa en set(value) con funciones como require.Se usa en @setter con raise ValueError(...).
Detección de errores en tiempo de compilaciónEl compilador verifica asignaciones inválidas (val, tipo, etc.).Requiere herramientas externas como mypy o Pyright.
Orientación a inmutabilidadFuerte énfasis en inmutabilidad por defecto (val).Enfocado en flexibilidad; la inmutabilidad es opcional y por convención.

Beneficios de Python

  • Sintaxis simple y directa para declarar variables sin necesidad de palabras clave adicionales.
    Esto reduce el ruido visual y permite concentrarse en la lógica del programa, lo cual es útil en prototipos, scripts o enseñanza.
    Aun cuando sacrifica la expresividad explícita de la intención (como distinguir entre val y var), favorece la fluidez al escribir código rápidamente.
  • Flexibilidad total para reasignar variables o cambiar tipos en tiempo de ejecución.
    Esta libertad es valiosa en escenarios dinámicos como procesamiento de datos, scripting, pruebas rápidas o metaprogramación.
    Aunque puede dificultar el seguimiento del flujo de tipos, permite escribir código más adaptable y reutilizable sin rigidez estructural.
  • Sistema de propiedades mediante decoradores permite encapsular lógica con una sintaxis clara.
    Aunque más explícita que en Kotlin, ofrece un control fino sobre lectura, escritura y eliminación de atributos.
  • Ideal para scripting, prototipado rápido y enseñanza por su bajo nivel de complejidad inicial.
    Los principiantes pueden centrarse en conceptos esenciales sin verse abrumados por la sintaxis del lenguaje.
  • Compatibilidad con anotaciones opcionales (Final, tipos) permite reforzar buenas prácticas con herramientas externas.
    Esto facilita una adopción progresiva de prácticas robustas sin imponerlas desde el inicio.

Limitaciones de Python

  • No existe una forma nativa de restringir la reasignación o mutabilidad de variables.
    Esto dificulta expresar la intención de inmutabilidad en la interfaz pública de una biblioteca. Aunque existen convenciones (MAYÚSCULAS) y herramientas como Final, ninguna impone restricciones reales en tiempo de ejecución.
  • Las garantías de tipo o de estado son opcionales y dependen de herramientas externas.
    Python no valida las anotaciones de tipo ni impide errores como asignar un valor inesperado.
    Esto puede llevar a fallos en tiempo de ejecución que, en lenguajes como Kotlin, se detectan en compilación.
  • Las propiedades deben definirse manualmente con decoradores.
    Aunque poderosas, requieren más código explícito y repetitivo que en Kotlin, donde cada variable es una propiedad con get/set implícitos desde el inicio.
  • No hay modificadores de acceso reales (private, protected).
    El uso de convenciones como __atributo ayuda a ocultar implementación, pero no impide el acceso desde fuera. Esto complica la encapsulación y puede dificultar la evolución segura de bibliotecas.
  • La flexibilidad del lenguaje dificulta razonar formalmente sobre el estado de los objetos.
    Al permitir reasignaciones y cambios de tipo en cualquier momento, se vuelve más difícil garantizar invariantes internas o aplicar transformaciones seguras sin pruebas exhaustivas o validaciones adicionales.
  • La falta de inmutabilidad por defecto complica el estilo funcional.
    En programación funcional, la inmutabilidad es clave para componer funciones puras y evitar efectos colaterales.
    Como Python permite mutar estructuras y reasignar nombres libremente, es más fácil introducir errores sutiles y más difícil aplicar enfoques funcionales de forma segura y expresiva.

🎯 Conclusiones

A lo largo de esta lección exploramos cómo se declaran y gestionan las variables en Python, y cómo este modelo difiere profundamente del enfoque expresivo y seguro de Kotlin.

Python privilegia la simplicidad y flexibilidad, permitiendo reasignaciones sin restricciones y eliminando la necesidad de palabras clave como val o var. Esto facilita la escritura de código rápido y dinámico, especialmente útil en scripts, prototipos y enseñanza. Sin embargo, también sacrifica garantías importantes como la inmutabilidad por defecto, la validación de tipos en compilación o el control explícito de visibilidad y mutabilidad.

En contraste con Kotlin, donde cada variable es también una propiedad capaz de encapsular lógica de forma declarativa, en Python se requiere definir manualmente cada aspecto mediante decoradores. Esto otorga poder, pero también impone más esfuerzo y atención al detalle para lograr un diseño robusto.

Finalmente, vimos cómo algunas herramientas del ecosistema —como Final, mypy o @property— permiten recuperar parte de esa expresividad, aunque nunca con la misma fuerza ni inmediatez que en un lenguaje estáticamente tipado y orientado a la inmutabilidad por defecto.

🔑 Puntos clave

  • En Python, una variable se crea al asignarle un valor: no necesita declaración previa ni palabra clave.
  • No hay distinción nativa entre variables mutables e inmutables; toda variable puede ser reasignada.
  • La inmutabilidad depende del tipo del objeto (por ejemplo, int es inmutable; list es mutable).
  • No existe soporte real para constantes, pero se pueden simular con convenciones (MAYÚSCULAS) o Final.
  • Las propiedades se implementan con decoradores (@property, @setter, @deleter), lo que permite encapsular validaciones y lógica de acceso.
  • Python no impone restricciones, pero sí ofrece herramientas opcionales para lograr mayor seguridad y expresividad.

🧰 ¿Qué nos llevamos?

Python ofrece un entorno flexible y accesible, ideal para quienes priorizan rapidez de desarrollo, exploración interactiva o enseñanza. Su sistema de variables permite escribir código sin fricciones, pero a costa de perder garantías que en otros lenguajes —como Kotlin— están integradas desde la base.

Este enfoque no es malo por sí mismo, pero te delega a ti, como quien diseña las bibliotecas, la responsabilidad de proteger tus invariantes. Tendrás que aplicar disciplina, convenciones, y herramientas adicionales si buscas ofrecer una API segura y mantenible.

Elegir entre flexibilidad y restricciones no es una cuestión de preferencia personal, sino de adecuación al problema y al contexto. En un script simple o una exploración de datos, la flexibilidad de Python brilla. En una biblioteca compartida y en evolución, podrías echar de menos las garantías de un sistema como el de Kotlin.

La clave es comprender qué te ofrece cada lenguaje, y cómo usar sus herramientas —y sus límites— a tu favor.

📖 ¿Con ganas de más?

🔥 Referencias recomendadas

  • 🌐 Python Constants: Improve Your Code’s Maintainability – Real Python en Real Python por Leodanis Pozo Ramos:
    Este artículo ofrece una guía completa sobre el uso de constantes en Python para mejorar la legibilidad, mantenibilidad y seguridad del código. Explica qué son las constantes, por qué usarlas y cómo implementarlas en proyectos reales, a pesar de que Python no tiene una sintaxis nativa para constantes estrictas. Cubre buenas prácticas, uso de constantes predefinidas y estrategias para organizarlas (como módulos dedicados, archivos de configuración o variables de entorno). Además, presenta técnicas avanzadas para crear constantes verdaderamente inmutables usando clases, @property, namedtuple, @dataclass y más.