Un programa de ingeniería es, casi siempre, una cadena de cálculos sobre magnitudes físicas. Este tema da las piezas: cómo se guarda un dato, de qué tipo es, cómo se combina con otros y —lo que más importa en esta materia— cómo se evita el error de unidades, que en el Tema 9 identificamos como el más frecuente y el más caro de todos.
Antes de empezar: ¿cuánto es 7 / 2? ¿Y 7 // 2? ¿Y "7" + "2"? Las tres expresiones son válidas en Python y dan 3.5, 3 y "72". Si las tres te parecen evidentes, este tema te servirá de repaso rápido. Si alguna te ha sorprendido, ahí está exactamente el tipo de error que vamos a aprender a evitar.
Al terminar serás capaz de…
- declarar variables con nombres significativos y explicar qué hace una asignación;
- distinguir entero, real, cadena y booleano, y saber de qué tipo es cada dato de un programa;
- convertir entre tipos y reconocer los errores de tipo más frecuentes;
- usar los operadores aritméticos, incluidos la división entera, el resto y la potencia;
- construir condiciones con operadores relacionales y lógicos;
- aplicar la precedencia de operadores y evaluar una expresión paso a paso;
- pedir datos por teclado y presentar resultados con el formato adecuado;
- escribir un cálculo técnico documentando unidades y redondeando con criterio;
- comprobar un programa con casos de prueba de resultado conocido.
1. Variables y asignación
Una variable es un nombre asociado a un valor guardado en la memoria. La asignación es la operación que establece esa asociación, y se escribe con el signo igual.
par = 0.35 # N·m
relacion = 9
rendimiento = 0.85
par_salida = par * relacion * rendimiento
print(par_salida) # 2.6775
El igual de la programación no es el de las matemáticasEn matemáticas x = x + 1 es una ecuación sin solución. En programación es una instrucción perfectamente normal: «toma el valor actual de x, súmale uno y guarda el resultado otra vez en x». El igual no afirma una igualdad: ordena guardar. Se lee de derecha a izquierda: primero se calcula lo de la derecha, después se guarda en el nombre de la izquierda.
lecturas = 0
lecturas = lecturas + 1 # ahora vale 1
lecturas = lecturas + 1 # ahora vale 2
lecturas += 1 # forma abreviada: ahora vale 3
Identificadores: las reglas y las costumbres
Cómo se nombra una variable
| Regla o costumbre | Bien | Mal |
| Empieza por letra o guion bajo, nunca por cifra. | par_motor | 2par |
| Sin espacios; se separan las palabras con guion bajo. | tiempo_riego_s | tiempo riego |
| Sin tildes ni eñes, por compatibilidad. | presion | presión |
| Distingue mayúsculas de minúsculas. | Elegir una y mantenerla | Par y par a la vez |
| No usar palabras reservadas del lenguaje. | lista_medidas | for, if, print |
| Que diga la magnitud y, si hay duda, la unidad. | caudal_l_h | q |
Constantes: Python confía en ti. Python no tiene constantes de verdad; se usa el convenio de escribir en mayúsculas los valores que no deben cambiar durante la ejecución: UMBRAL_RIEGO = 500. El lenguaje te dejará modificarla, pero cualquiera que lea el programa sabrá que no debe. Y reunir todas esas constantes al principio del archivo tiene una ventaja práctica enorme: ajustar el sistema en el huerto se convierte en cambiar tres números en el primer bloque, en lugar de buscarlos repartidos por doscientas líneas.
2. Los cuatro tipos de datos
Los tipos básicos y su papel en el KR-1
| Tipo | En Python | Ejemplos | Para qué en el proyecto |
| Entero | int | 0, 2847, -15 | Lecturas del ADC, número de ciclos, contadores. |
| Real | float | 0.35, 2.6775, 3.3 | Tensiones, pares, caudales: casi toda magnitud física. |
| Cadena | str | "KR-1", "riego" | Mensajes, nombres de tema MQTT, etiquetas del registro. |
| Booleano | bool | True, False | Estados: válvula abierta, modo manual, sensor válido. |
lectura = 2847 # int
tension = 2.29 # float
estado = "regando" # str
valvula_abierta = True # bool
print(type(lectura)) # <class 'int'>
print(type(tension)) # <class 'float'>
Python averigua el tipo, pero el tipo existeNo hay que declararlo: Python lo deduce del valor. Eso es cómodo y tiene una consecuencia importante: el tipo de una variable puede cambiar a lo largo del programa, y ahí empiezan los errores. Si una variable vale a veces un número y a veces un texto, el programa funcionará hasta el día en que reciba el otro. La disciplina es propia, no del lenguaje: una variable, un tipo, durante todo el programa.
Los booleanos van en mayúscula inicial: True y False, no true ni verdadero. Y son mucho más útiles de lo que parecen: casi todo el programa de control del Tema 18 se reduce a comprobar y modificar unos pocos booleanos de estado.
Los reales no son exactosPrueba a ejecutar print(0.1 + 0.2): Python responde 0.30000000000000004. No es un fallo de Python: es que los números reales se guardan en binario con un número finito de bits, y muchos decimales no tienen representación exacta, igual que 1/3 no se puede escribir exactamente en decimal. La consecuencia práctica es inmediata: nunca compares dos reales con igualdad. En lugar de if tension == 3.3, escribe if abs(tension - 3.3) < 0.01. Es la tolerancia del Tema 2 aplicada al código.
3. Conversión de tipos
Convertir un dato de un tipo a otro se hace con funciones cuyo nombre es el del tipo destino.
int("2847") # 2847 texto a entero
float("2.29") # 2.29 texto a real
str(2847) # "2847" número a texto
int(2.9) # 2 trunca, NO redondea
round(2.9) # 3 redondea
int(True) # 1 un booleano es 1 o 0
int() trunca y round() redondeaEs una diferencia que se paga caro en un cálculo técnico. int(2.9) vale 2: descarta la parte decimal sin mirarla. round(2.9) vale 3. Si calculas cuántas vueltas necesita un husillo y usas int(), te quedarás sistemáticamente corto. Elige con intención, y cuando lo que quieras sea «al menos tantas», usa math.ceil().
Los errores de tipo que vas a cometer
| Lo que escribes | Qué pasa | Cómo se arregla |
"7" + 2 | TypeError: no se puede sumar texto y número. | int("7") + 2 |
"7" + "2" | No da error: da "72". Concatena. | Convertir antes: int("7") + int("2") |
"3" * 2 | No da error: da "33". Repite el texto. | Convertir antes de multiplicar. |
int("2,29") | ValueError: la coma no es un separador decimal válido. | Usar punto, o sustituir la coma antes. |
int("2.29") | ValueError: int no acepta decimales en texto. | int(float("2.29")) |
print("Par: " + par) | TypeError si par es un número. | print("Par:", par) o str(par) |
El más peligroso es el segundo. "7" + "2" no produce ningún mensaje de error: produce "72" y el programa sigue como si nada. Es un error lógico de los del Tema 12: aparece cuando un dato que creías número llega como texto, y eso pasa siempre que el dato viene de fuera —del teclado, de un archivo o de la red—. De ahí la regla de la sección siguiente.
4. Operadores aritméticos
Los siete operadores aritméticos
| Operador | Operación | Ejemplo | Resultado |
+ | Suma | 7 + 2 | 9 |
- | Resta | 7 - 2 | 5 |
* | Multiplicación | 7 * 2 | 14 |
/ | División real | 7 / 2 | 3.5 — siempre real |
// | División entera | 7 // 2 | 3 |
% | Resto o módulo | 7 % 2 | 1 |
** | Potencia | 7 ** 2 | 49 |
La división entera y el resto sirven de verdadParecen curiosidades y resuelven dos problemas cotidianos. Con división entera se reparte: 137 segundos son 137 // 60 = 2 minutos. Con el resto se obtiene lo que sobra —137 % 60 = 17 segundos— y se detectan periodicidades: if minuto % 15 == 0 es «cada cuarto de hora», que es exactamente cómo se programa la cadencia de medida del Tema 18.
# Funciones matemáticas: hay que importar el módulo math
import math
print(math.pi) # 3.141592653589793
print(math.sqrt(2)) # 1.4142135623730951
print(math.ceil(4.1)) # 5 redondeo hacia arriba
print(math.floor(4.9)) # 4 redondeo hacia abajo
print(math.radians(30)) # 0.5235987755982988
print(math.sin(math.radians(30))) # 0.49999999999999994
Las funciones trigonométricas trabajan en radianes. Es el error de unidades del Tema 9 con otro disfraz: math.sin(30) no vale 0,5, porque interpreta 30 radianes. Hay que convertir con math.radians(). Y fíjate en el último resultado: 0,49999999999999994 en lugar de 0,5, otra vez la inexactitud de los reales.
5. Operadores relacionales y lógicos
Los operadores relacionales comparan dos valores y devuelven un booleano. Son la materia prima de las decisiones del Tema 14.
Comparar y combinar
| Operador | Significa | Ejemplo | Resultado |
== | Igual a | 500 == 500 | True |
!= | Distinto de | 500 != 480 | True |
< > | Menor, mayor | 410 < 500 | True |
<= >= | Menor o igual, mayor o igual | 500 >= 500 | True |
and | Las dos condiciones a la vez | True and False | False |
or | Al menos una de las dos | True or False | True |
not | Lo contrario | not True | False |
Un igual asigna, dos iguales comparanEs el error clásico y el que más tiempo hace perder. umbral = 500 guarda 500 en la variable; umbral == 500 pregunta si vale 500. Confundirlos dentro de un if produce un SyntaxError en Python —por suerte—, pero la confusión de fondo persiste: al leer código hay que distinguir cuándo se está ordenando y cuándo preguntando.
# Las condiciones del riego, tal como quedarán en el Tema 14
humedad = 410
hora = 8
modo_manual = False
seco = humedad < 500
en_horario = 7 <= hora < 10 # comparación encadenada, legal en Python
hay_que_regar = seco and en_horario and not modo_manual
print(seco, en_horario, hay_que_regar) # True True True
Dar nombre a las condiciones cambia la legibilidadComparar las dos versiones del mismo código: if humedad < 500 and 7 <= hora < 10 and not modo_manual: frente a if hay_que_regar:. La segunda se lee de un golpe, se puede imprimir para depurar y se puede reutilizar. Guardar una condición en un booleano con nombre es la técnica más rentable de todo el bloque, y se usará sin descanso en los temas 14 y 18.
6. Precedencia y evaluación de expresiones
Una expresión es una combinación de valores, variables y operadores que produce un resultado. El orden en que se aplican los operadores lo fija la precedencia.
Precedencia, de mayor a menor
| Orden | Operadores |
| 1 | Paréntesis ( ) |
| 2 | Potencia ** |
| 3 | Signo negativo -x |
| 4 | Multiplicación y divisiones * / // % |
| 5 | Suma y resta + - |
| 6 | Relacionales < <= > >= == != |
| 7 | not |
| 8 | and |
| 9 | or |
Evaluación paso a paso
resultado = 2 + 3 * 4 ** 2 / 8
Cómo evalúa Python esa expresión
| Paso | Se aplica | Expresión resultante |
| 1 | Potencia: 4 ** 2 | 2 + 3 * 16 / 8 |
| 2 | Multiplicación: 3 * 16 | 2 + 48 / 8 |
| 3 | División: 48 / 8 | 2 + 6.0 |
| 4 | Suma | 8.0 |
Los paréntesis son gratis y valen mucho. Nadie te va a felicitar por memorizar la tabla de precedencias, y en cambio un paréntesis mal puesto puede costar una tarde. Escribe (a + b) / 2 aunque sepas que no hace falta, y sobre todo escribe (seco and en_horario) or modo_forzado en lugar de fiarte de que and tiene más precedencia que or. El código se escribe para leerlo, no para demostrar nada.
Piensa: ¿qué vale 2 ** 3 ** 2? Si crees que 64, la precedencia te ha traicionado: la potencia se asocia de derecha a izquierda, así que es 2 ** 9 = 512. Es el caso donde ni conocer la tabla salva: la única defensa es el paréntesis.
7. Entrada y salida de datos
# input() SIEMPRE devuelve una cadena de texto
texto = input("Introduce el par del motor en N·m: ")
par = float(texto) # hay que convertir
print("El par vale", par, "N·m")
input() devuelve texto, siempreAunque el usuario escriba 0.35, lo que llega es la cadena "0.35". Si la usas sin convertir, par * 9 no multiplicará: repetirá el texto nueve veces. Es el error de tipo más frecuente del curso y es silencioso, porque no produce ningún mensaje. Regla: todo input() va seguido de su conversión, y lo mismo vale para cualquier dato que llegue de un archivo o de la red en el Tema 16.
Formato de la salida
par = 0.35
relacion = 9
rendimiento = 0.85
par_salida = par * relacion * rendimiento
print(par_salida) # 2.6775000000000003
print(round(par_salida, 2)) # 2.68
print(f"Par de salida: {par_salida:.2f} N·m") # Par de salida: 2.68 N·m
print(f"Relación {relacion}:1 · rendimiento {rendimiento:.0%}")
# Relación 9:1 · rendimiento 85%
Las cadenas formateadasUna cadena precedida de f permite insertar valores entre llaves, con un formato indicado tras dos puntos: {valor:.2f} significa «real con dos decimales» y {valor:.0%}, «porcentaje sin decimales». Es la forma de presentar un resultado técnico con las cifras significativas que los datos sostienen, y no las diecisiete que arrastra el cálculo. Del Tema 2: escribir 2,6775000000000003 N·m no es más preciso, es menos honesto.
8. Calcular magnitudes técnicas con Python
Aquí es donde este tema se separa de un curso de programación al uso. Un cálculo de ingeniería escrito en código debe cumplir las mismas condiciones que la memoria de cálculo del Tema 9: datos con unidades, hipótesis declaradas y resultado con cifras sensatas.
"""Accionamiento del KR-1: cálculo de la cadena de potencia.
Datos del catálogo del motor y del reductor. Unidades en el SI.
Hipótesis: rendimiento de cada etapa 0,95; de los cojinetes 0,94.
"""
import math
# --- Datos ---
PAR_MOTOR_NM = 0.35 # N·m, par nominal de catálogo
N_MOTOR_RPM = 1800 # min-1, velocidad nominal
RELACION = 9 # adimensional, dos etapas de 3
REND_ETAPA = 0.95 # por etapa de engranajes
REND_COJINETES = 0.94
# --- Cálculo ---
omega_motor = 2 * math.pi * N_MOTOR_RPM / 60 # rad/s
potencia_entrada = PAR_MOTOR_NM * omega_motor # W
rendimiento = REND_ETAPA ** 2 * REND_COJINETES
potencia_salida = potencia_entrada * rendimiento # W
n_salida = N_MOTOR_RPM / RELACION # min-1
par_salida = PAR_MOTOR_NM * RELACION * rendimiento # N·m
# --- Resultados ---
print(f"Velocidad angular de entrada: {omega_motor:.1f} rad/s")
print(f"Potencia de entrada: {potencia_entrada:.1f} W")
print(f"Rendimiento total: {rendimiento:.2f}")
print(f"Potencia de salida: {potencia_salida:.1f} W")
print(f"Velocidad de salida: {n_salida:.0f} min-1")
print(f"Par de salida: {par_salida:.2f} N·m")
Las cinco reglas de un cálculo técnico escrito en Python
| Regla | Cómo se aplica |
| 1. Unidad en el nombre o en el comentario | PAR_MOTOR_NM, o # N·m al lado. Nunca una variable sin unidad conocida. |
| 2. Datos separados del cálculo | Bloque de constantes arriba, cálculo debajo. Cambiar un dato no obliga a buscar por todo el archivo. |
| 3. Hipótesis escritas | En el comentario inicial del archivo, como en la memoria del Tema 9. |
| 4. Un paso, una línea | Una línea gigante es imposible de depurar. Los pasos intermedios se guardan en variables con nombre. |
| 5. Resultado con cifras significativas | Formatear la salida. Y si el dato de partida tenía dos cifras, el resultado no puede tener seis. |
El comentario entre triples comillas. El bloque del principio, escrito entre """, es la forma convencional de documentar un archivo o una función en Python. Se llama docstring y tiene una ventaja sobre un comentario normal: las herramientas lo leen y lo muestran como ayuda. Es el equivalente en código de la cabecera de un plano del Tema 3.
9. Comprobar con casos de resultado conocido
Un cálculo escrito en código puede estar mal y dar un número plausible. La única defensa es comprobarlo con casos cuyo resultado se conoce por otra vía.
Casos de prueba del programa anterior
| Caso | Entrada | Resultado esperado | De dónde sale el valor esperado |
| Caso base | Los datos del catálogo | 2,68 N·m | Cálculo a mano del Tema 9. |
| Rendimiento perfecto | REND_ETAPA = 1, REND_COJINETES = 1 | 3,15 N·m | 0,35 · 9, sin pérdidas: comprueba la fórmula. |
| Relación unidad | RELACION = 1 | Par de salida ≈ par de entrada | Sin reductor no hay multiplicación de par. |
| Orden de magnitud | Los datos del catálogo | Decenas de vatios | Un motor pequeño de 12 V no da kilovatios. |
| Caso límite | RELACION = 0 | Debería avisar, no calcular | Una relación nula no tiene sentido físico. |
Los casos extremos son los que encuentran los erroresEl caso base solo confirma lo que ya sabías. Los que descubren fallos son los otros cuatro: poner el rendimiento a 1 verifica la fórmula desnuda; poner la relación a 1 comprueba que no hay un factor colado; el orden de magnitud detecta un error de unidades de mil veces; y el caso absurdo revela que el programa no comprueba sus datos de entrada. Es el mismo razonamiento del Tema 9 —contrastar por dos caminos—, ahora aplicado al código.
# Comprobación automática: si la condición es falsa, el programa avisa
par_esperado = 2.68
assert abs(par_salida - par_esperado) < 0.01, "El par de salida no coincide"
print("Comprobación superada")
assert: la comprobación que no se olvida. Escribir la comprobación dentro del programa tiene una ventaja sobre hacerla a mano: se vuelve a ejecutar cada vez que se ejecuta el programa. Si mañana alguien cambia una constante y rompe el cálculo, el assert lo avisa al instante en lugar de dejar pasar un resultado equivocado. Y fíjate en la comparación: abs(...) < 0.01, nunca ==, por la inexactitud de los reales de la sección 2.
Comprueba lo que has aprendido
Este tema se demuestra con un cálculo técnico escrito en código que otra persona pueda revisar como revisaría una memoria.
Qué debería mostrar tu trabajo
| Aspecto | Qué debes demostrar | Evidencias posibles |
| Tipos y conversión | Que sabes de qué tipo es cada dato y convieres lo que llega de fuera. | Programa con input() convertido, tres errores de tipo provocados y explicados. |
| Operadores | Que usas división entera y resto donde toca y controlas la precedencia. | Conversión de segundos a minutos y segundos; una expresión evaluada paso a paso en una tabla. |
| Condiciones con nombre | Que guardas las condiciones en booleanos legibles. | Las condiciones del riego como tres booleanos con nombre, impresos para depurar. |
| Cálculo técnico | Que aplicas las cinco reglas: unidades, datos separados, hipótesis, un paso por línea y formato. | Programa de cálculo con docstring, constantes en mayúsculas y salida formateada. |
| Comprobación | Que compruebas con casos de resultado conocido, incluidos los extremos. | Tabla de casos de prueba con los cinco tipos y al menos un assert en el código. |
Prueba reveladora: ejecuta tu cálculo con el rendimiento a 1 y comprueba que el resultado es el producto desnudo. Si no lo es, hay un factor de más o de menos escondido en alguna línea.
Glosario del tema
- Asignación
- Operación que guarda un valor en una variable; se evalúa primero la derecha y después se guarda en la izquierda.
- Booleano
- Tipo de dato con dos valores posibles, verdadero y falso.
- Cadena formateada
- Cadena precedida de f en la que se insertan valores entre llaves con un formato indicado.
- Concatenar
- Unir dos cadenas de texto una tras otra.
- Constante
- Valor que no debe cambiar durante la ejecución; en Python se señala por convenio con el nombre en mayúsculas.
- Conversión de tipo
- Transformación de un dato de un tipo a otro mediante una función como int, float o str.
- División entera
- División que descarta la parte decimal del cociente.
- Docstring
- Bloque de texto entre triples comillas que documenta un archivo o una función.
- Entero
- Tipo de dato numérico sin parte decimal.
- Expresión
- Combinación de valores, variables y operadores que produce un resultado.
- Identificador
- Nombre con el que se designa una variable, una constante o una función.
- Módulo (operador)
- Resto de una división entera; sirve para detectar periodicidades.
- Operador lógico
- Operador que combina booleanos: and, or y not.
- Operador relacional
- Operador que compara dos valores y devuelve un booleano.
- Precedencia
- Orden en que se aplican los operadores de una expresión.
- Real
- Tipo de dato numérico con parte decimal, guardado de forma aproximada en binario.
- Variable
- Nombre asociado a un valor guardado en la memoria.
Resumen esencial
- El igual de la programación no afirma una igualdad: ordena guardar, y se lee de derecha a izquierda.
- Los nombres se escriben en minúsculas con guion bajo, sin tildes, y deben decir la magnitud y su unidad.
- Python no tiene constantes: se usa el convenio de las mayúsculas, y reunirlas al principio permite ajustar el sistema cambiando tres números.
- Hay cuatro tipos básicos: entero, real, cadena y booleano. Python deduce el tipo, pero la disciplina de no cambiarlo es tuya.
- Los reales no son exactos: nunca se comparan con igualdad, sino con una tolerancia.
int() trunca y round() redondea; en un cálculo técnico la diferencia se nota.
- Sumar dos textos no da error, da una concatenación: es el error de tipo más peligroso porque es silencioso.
- La división entera reparte y el resto detecta periodicidades: así se programa la cadencia de un sistema de control.
- Las funciones trigonométricas trabajan en radianes, y olvidarlo es el error de unidades del Tema 9 con otro disfraz.
- Un igual asigna y dos iguales comparan.
- Guardar una condición en un booleano con nombre es la técnica más rentable del bloque.
- Los paréntesis son gratis: se escriben aunque la precedencia no los exija.
input() devuelve siempre texto, así que va seguido de su conversión, igual que cualquier dato que llegue de un archivo o de la red.
- Un cálculo técnico en código lleva unidades, datos separados del cálculo, hipótesis escritas, un paso por línea y salida formateada.
- Los casos de prueba que encuentran errores son los extremos: rendimiento unidad, relación unidad, orden de magnitud y caso absurdo.
- Un
assert deja la comprobación dentro del programa, de modo que se repite cada vez que se ejecuta.
Fuentes y recursos fiables