Capítulo 3 de 17 13 secciones 22 min

Compartir

Variables, números y texto

Los cuatro tipos que vas a usar siempre, el error de sumar texto con número, y por qué 0,1 más 0,2 no da 0,3.

Una variable es un nombre pegado a un valor, nada más. Yo uso cuatro tipos casi todo el tiempo: int para enteros, float para decimales, str para texto y bool para verdadero o falso. Lo que te va a pasar la primera semana es sumar un número con un texto que parecía número, y se arregla convirtiéndolo con int() o float().

Una variable es una etiqueta, no una caja

Hola! Vamos con lo que hay dentro de una variable, que es la base de todo lo demás 🌸

Casi siempre te van a explicar que una variable es una caja donde guardas algo. Yo prefiero otra imagen, porque te va a ahorrar un dolor de cabeza más adelante: una variable es una etiqueta que le pegas a un valor.

ciudad = 'Arequipa'
ventas = 3
promedio = 1250.75

print(ciudad, ventas, promedio)
Arequipa 3 1250.75

El signo igual no significa "es igual a" como en matemáticas. Significa "desde ahora, este nombre apunta a este valor". Por eso esto que parecería una locura funciona sin problema:

contador = 10
contador = contador + 5

print(contador)
15

Se lee de derecha a izquierda: agarra lo que hay en contador, súmale 5, y pega la etiqueta contador al resultado.

Cómo se nombran las variables

Hay reglas que Python obliga y convenciones que obliga la comunidad. Las dos importan.

Lo que Python no te deja: empezar con un número, usar espacios, usar guiones, o usar una palabra reservada como class o for.

Lo que se acostumbra, y viene escrito en un documento que se llama PEP 8 (la guía de estilo oficial de Python):

  • 🐍 Todo en minúsculas y las palabras separadas con guion bajo: total_ventas, fecha_de_corte. Eso se llama snake_case.
  • 📝 Nombres que digan qué hay dentro. df2 no dice nada; ventas_limpias sí.
  • 🚫 Nada de tildes ni ñ, aunque Python las acepte. Te van a dar problemas al compartir código.

Te lo digo por experiencia: el código que escribes hoy lo lee otra persona dentro de tres meses, y muchas veces esa otra persona eres tú 😅

Árbol para decidir el tipo de una variable en Python: si guarda letras es str, si guarda verdadero o falso es bool, y si guarda un número es int cuando no lleva decimales y float cuando sí. Si el dato vino de un archivo, el número también llega como str.
El tipo no lo eliges tú, lo trae el dato. Y la casilla rosada es la que se lleva la primera semana de todo el mundo: un número que viene de un archivo es texto hasta que lo conviertas.

Los cuatro tipos que vas a usar siempre

Python tiene muchos tipos, pero para datos son cuatro los que aparecen todo el tiempo.

unidades = 12                 # int:   numero entero
monto = 1250.75               # float: numero con decimales
cliente = 'Minimarket El Sol' # str:   texto
pago = True                   # bool:  verdadero o falso

print(type(unidades))
print(type(monto))
print(type(cliente))
print(type(pago))
<class 'int'>
<class 'float'>
<class 'str'>
<class 'bool'>

type() es la pregunta "qué eres tú" y la vas a usar más de lo que crees. Cuando algo no funcione y no entiendas por qué, imprime el tipo antes de seguir buscando 🔍

Un detalle sobre bool: por dentro es un número. Eso parece un dato curioso y en realidad es un truco que vas a usar seguido.

print(True + True)
print(sum([True, False, True, True]))
2
3

Sumar una lista de verdaderos y falsos te da cuántos verdaderos hay. Cuando lleguemos a pandas, así vas a contar cuántas filas cumplen una condición.

El error de la primera semana

Este te va a pasar. A todo el mundo le pasa, así que mejor que te pase aquí conmigo y no un viernes a las siete.

unidades = '12'      # ojo: vino como texto, con comillas
precio = 40

print(unidades * precio)
12121212121212121212121212121212121212121212121212121212121212121212121212121212

Ajá 😅

Multiplicar un texto por un número no es un error para Python: es repetir el texto esa cantidad de veces. Así que te repitió "12" cuarenta veces y no te avisó de nada.

Ese es el peor tipo de error: el que no falla. Un error que revienta lo ves; este te deja seguir trabajando con un resultado que no significa nada.

Con la suma sí revienta, y menos mal:

print(unidades + precio)
TypeError: can only concatenate str (not "int") to str

Léelo con calma que el mensaje es bueno: "solo puedo concatenar texto con texto, y me diste un int". O sea, Python vio un texto a la izquierda y asumió que querías pegar palabras.

La solución es convertir:

unidades = int('12')

print(unidades + precio)
print(type(unidades))
52
<class 'int'>

Las tres conversiones que vas a usar son int(), float() y str(). Y una advertencia que te ahorra rato: int() con un texto que tenga decimales no funciona.

int('40.5')
ValueError: invalid literal for int() with base 10: '40.5'

Ahí hay que pasar por float() primero, o directamente usar float() si no necesitas un entero.

Por qué 0,1 más 0,2 no da 0,3

Este es de los que más desconciertan, y no es un bug de Python.

print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
0.30000000000000004
False

No te asustes. Pasa en todos los lenguajes, y en Excel también (solo que Excel te lo esconde al mostrarte el número).

La razón es que la computadora guarda los decimales en binario, y hay decimales que en binario no tienen representación exacta, igual que un tercio no la tiene en decimal: 0,3333... nunca termina.

Lo que importa son las dos consecuencias prácticas:

  • ⚠️ Nunca compares dos decimales con ==. Usa round() o compara la diferencia.
  • 💰 Para dinero, redondea al final y no en cada paso. Si el proyecto es contable de verdad, existe un tipo llamado Decimal que guarda los números exactos.
print(round(0.1 + 0.2, 2) == 0.3)

from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2'))
True
0.3

Fíjate en que Decimal recibe el número entre comillas. Si le pasas Decimal(0.1) le estás dando el float que ya venía roto, y no arregla nada.

Texto, que es la mitad de tu trabajo

En datos reales, el 90% de lo sucio es texto: nombres con espacios de más, ciudades escritas de cuatro formas, números que vinieron como cadena. Así que estos métodos los vas a usar muchísimo.

cliente = '  minimarket EL SOL  '

print(cliente.strip())            # quita espacios de los extremos
print(cliente.strip().title())    # Primera Letra De Cada Palabra
print(cliente.strip().lower())    # todo minusculas
print(cliente.replace('EL', 'el').strip())
minimarket EL SOL
Minimarket El Sol
minimarket el sol
minimarket el SOL

Un detalle importante: estos métodos no modifican la variable, te devuelven una copia. Si quieres conservar el cambio hay que reasignarlo.

cliente.strip()
print(repr(cliente))              # sigue con sus espacios

cliente = cliente.strip()
print(repr(cliente))
'  minimarket EL SOL  '
'minimarket EL SOL'

Usé repr() para que se vean las comillas y los espacios. En la primera línea siguen ahí, aunque hayamos llamado a .strip() justo antes: el método devolvió una copia limpia y nadie la guardó.

Ese repr() va a ser tu mejor amigo depurando texto, porque un espacio de más es invisible con print normal 🔍

Y el que más rinde de todos, .split(), que parte un texto en una lista:

fila = 'C0045;Arequipa;Minimarket;480.37'
partes = fila.split(';')

print(partes)
print(partes[1])
print(float(partes[3]) * 2)
['C0045', 'Arequipa', 'Minimarket', '480.37']
Arequipa
960.74

Eso de arriba es, en miniatura, lo que hace pandas cuando lee un CSV 📊

f-strings: la forma de armar texto

Antes había tres maneras de meter una variable dentro de un texto y todas eran incómodas. Desde Python 3.6 hay una sola que vale la pena, y se llama f-string: una f antes de la comilla y las variables entre llaves.

cliente = 'Minimarket El Sol'
monto = 1250.756

print(f'{cliente} compró S/{monto}')
print(f'{cliente} compró S/{monto:.2f}')
print(f'{cliente:>25} | S/{monto:>10.2f}')
Minimarket El Sol compró S/1250.756
Minimarket El Sol compró S/1250.76
        Minimarket El Sol | S/   1250.76

Esos dos puntos dentro de las llaves son el formato, y valen oro:

  • 💵 :.2f deja dos decimales. Para plata, siempre.
  • 📐 :>10 alinea a la derecha en diez espacios, que es lo que hace que una tabla impresa se vea derecha.
  • 🔢 :, pone el separador de miles: f'{1250000:,}' sale 1,250,000.

El error que da la primera vez es olvidar la f:

print('{cliente} compró algo')
{cliente} compró algo

No revienta, simplemente te imprime las llaves tal cual. Si ves llaves en tu salida, te faltó la f 🙃

None, que no es cero ni vacío

None es el valor que dice "aquí no hay nada". No es el 0, no es el texto vacío, es la ausencia.

fecha_ultima_compra = None

print(fecha_ultima_compra is None)
print(fecha_ultima_compra == 0)
True
False

Se compara con is None y no con == None. Es la convención de Python y hay razones técnicas, pero con que te acostumbres basta.

Esto importa muchísimo en datos: cuando un cliente no tiene fecha de última compra, ese hueco no es un cero. Y tratarlo como cero te cambia el promedio y todas las conclusiones que salgan de ahí.

Lo que Python considera vacío

Cualquier valor de Python se puede usar como si fuera verdadero o falso. Y cuáles son falsos hay que sabérselo, porque de aquí sale uno de los errores más caros que vas a cometer con datos 🕳️

for valor in [0, 0.0, '', '0', ' ', [], {}, None, 'n/a']:
    print(f'{repr(valor):<8} -> {bool(valor)}')
0        -> False
0.0      -> False
''       -> False
'0'      -> True
' '      -> True
[]       -> False
{}       -> False
None     -> False
'n/a'    -> True

Los cuatro que sorprenden 👀

  • 0️⃣ El cero es falso. El entero y el decimal.
  • 🔤 El texto '0' es verdadero, porque es un texto con un carácter dentro. El cero de mentira es verdadero y el de verdad es falso.
  • Un espacio también es verdadero. Una celda que parece vacía en el Excel y trae un espacio, para Python tiene contenido.
  • 📭 La lista vacía y el diccionario vacío son falsos, y eso sí es cómodo: if resultados: se lee "si hay resultados".

El cero que desaparece del promedio

Ahora el error. Escribir if descuento: parece que dice "si vino el descuento". Lo que dice de verdad es "si el descuento no es cero ni nulo" 😖

descuentos = [15.0, 0.0, 8.5, None, 0.0, 12.0]

con_if = [d for d in descuentos if d]
con_is = [d for d in descuentos if d is not None]

print('con if d            :', con_if, '->', len(con_if), 'clientes')
print('con if d is not None:', con_is, '->', len(con_is), 'clientes')
print('descuento promedio, primera forma :',
      round(sum(con_if) / len(con_if), 2))
print('descuento promedio, segunda forma :',
      round(sum(con_is) / len(con_is), 2))
con if d            : [15.0, 8.5, 12.0] -> 3 clientes
con if d is not None: [15.0, 0.0, 8.5, 0.0, 12.0] -> 5 clientes
descuento promedio, primera forma : 11.83
descuento promedio, segunda forma : 7.1

Mira los dos promedios. No se parecen en nada 😳

Los dos clientes con descuento cero son clientes reales a los que no se les dio descuento. El primer filtro los tira a la basura junto con el nulo, y el promedio sube de siete y pico a casi doce.

Nadie va a notar ese error mirando el resultado, porque once y pico de descuento promedio es un número perfectamente creíble. Y estarías reportando un 67% más de lo que es 💸

La regla, y es corta: para preguntar si un dato vino, is not None. Para preguntar si un dato está vacío, if. Son preguntas distintas y hay que elegir la que de verdad quieres.

is no es lo mismo que ==

Ya usaste is None arriba y no te expliqué por qué no es == None. Aquí va, con la sorpresa incluida:

leido = int('2500')
escrito = 2500

print('valen lo mismo:', leido == escrito)
print('son el mismo  :', leido is escrito)

leido_chico = int('250')
escrito_chico = 250

print('con 250, valen lo mismo:', leido_chico == escrito_chico)
print('con 250, son el mismo  :', leido_chico is escrito_chico)
valen lo mismo: True
son el mismo  : False
con 250, valen lo mismo: True
con 250, son el mismo  : True

Los mismos dos números, dos respuestas distintas 🤯

== pregunta ¿valen lo mismo?. is pregunta ¿son exactamente el mismo objeto en la memoria?, que es otra cosa.

Y el motivo de que 250 sí y 2500 no: Python guarda de antemano los enteros pequeños, de -5 a 256, y los reparte a quien los pida. Los grandes los crea nuevos cada vez. Es un detalle interno, puede cambiar entre versiones, y por eso mismo nunca compares números ni textos con is.

Con texto pasa lo mismo:

ciudad_a = 'Lima'
ciudad_c = ''.join(['Li', 'ma'])

print('valen lo mismo:', ciudad_a == ciudad_c)
print('son el mismo  :', ciudad_a is ciudad_c)
valen lo mismo: True
son el mismo  : False

Entonces, ¿por qué is None sí? Porque None es uno solo en todo el programa. No hay dos. Preguntar si algo es ese objeto es la pregunta correcta, y por eso es la forma recomendada 💜

Resumido: is solo con None, True y False. Para todo lo demás, ==.

Redondear tampoco es lo que crees

print('round(0.5) =', round(0.5))
print('round(1.5) =', round(1.5))
print('round(2.5) =', round(2.5))
print('round(3.5) =', round(3.5))
round(0.5) = 0
round(1.5) = 2
round(2.5) = 2
round(3.5) = 4

El 1,5 sube a 2 y el 2,5 baja a 2. No es un fallo 🧮

Se llama redondeo bancario, y la regla es: cuando el resto es exactamente medio, se redondea al par más cercano. Existe justamente para que los medios no se vayan todos hacia arriba y el total se infle.

montos = [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]

print('redondeando uno a uno   :', sum(round(m) for m in montos))
print('sumando y redondeando   :', round(sum(montos)))
print('con el redondeo del cole:', sum(int(m + 0.5) for m in montos))
redondeando uno a uno   : 50
sumando y redondeando   : 50
con el redondeo del cole: 55

Cincuenta contra cincuenta y cinco. Un 10% de diferencia en diez números, solo por cómo se redondea 💰

Y ahí ves para qué sirve el redondeo bancario: la mitad de los medios suben y la otra mitad bajan, así que el total se queda donde tenía que quedarse. El redondeo que te enseñaron en el colegio los sube todos y desvía el total hacia arriba.

Lo que importa en la práctica: redondea al final, una sola vez. Si redondeas en cada paso, cada redondeo mete su error y al final tienes un total que no cuadra con la suma de las partes. Y esa es la llamada de "el reporte no cuadra por dos soles" 📞

Ejercicios

1. Los cuatro tipos

Crea una variable de cada tipo con datos de una venta e imprime el tipo de cada una en una sola línea.

unidades = 8
monto = 340.5
canal = 'WhatsApp'
pagado = False

print(type(unidades), type(monto), type(canal), type(pagado))
<class 'int'> <class 'float'> <class 'str'> <class 'bool'>
2. El total de una venta

Con 8 unidades a S/34,90 cada una y 18% de IGV, imprime el total con dos decimales usando un f-string.

unidades = 8
precio = 34.90
igv = 0.18

total = unidades * precio * (1 + igv)
print(f'Total: S/{total:.2f}')
Total: S/329.46

Fíjate en que redondeé solo al mostrar, no al calcular. Si redondeas en cada paso, los centavos se te van yendo.

3. El texto que parecía número

Te llega '250' como texto y '1.5' también. Multiplícalos y muestra el resultado con un decimal.

unidades = '250'          # como llega del sistema
factor = '1.5'            # el multiplicador de la promocion

resultado = int(unidades) * float(factor)
print(f'{resultado:.1f}')
375.0

Ojo con hacer int(factor): ahí revienta con un ValueError, porque int() no acepta un texto con punto decimal.

4. Limpiar un nombre de cliente

De ' BODEGA doña ROSA ' saca 'Bodega Doña Rosa'.

sucio = '   BODEGA doña ROSA  '
limpio = sucio.strip().title()

print(repr(limpio))
'Bodega Doña Rosa'

Usé repr() a propósito: muestra las comillas, así compruebas que de verdad no quedaron espacios. Es mi truco favorito para depurar texto 🔍

5. Partir una fila de CSV

De '2026-04-29,Cusco,Web,154.83' imprime la ciudad y el monto multiplicado por 1,18.

fila = '2026-04-29,Cusco,Web,154.83'
partes = fila.split(',')

print(partes[1])
print(f'{float(partes[3]) * 1.18:.2f}')
Cusco
182.70
6. La comparación que falla

Comprueba que 1.1 + 2.2 no es igual a 3.3, y después arregla la comparación.

print(1.1 + 2.2)                       # dos productos de S/1.10 y S/2.20
print(1.1 + 2.2 == 3.3)
print(round(1.1 + 2.2, 10) == 3.3)
3.3000000000000003
False
True

Redondear a diez decimales suena exagerado y es justo el punto: el error del binario está mucho más allá, así que con redondear a cualquier cantidad razonable de decimales el problema desaparece.

7. Una tabla alineada

Imprime tres líneas con nombre de ciudad y monto, de forma que los montos queden alineados a la derecha.

datos = [('Lima', 12500.5), ('Arequipa', 980.25), ('Cusco', 145600.0)]

for ciudad, monto in datos:
    print(f'{ciudad:<12} S/{monto:>12,.2f}')
Lima         S/   12,500.50
Arequipa     S/      980.25
Cusco        S/  145,600.00

Ese :<12 alinea a la izquierda y :>12,.2f alinea a la derecha con separador de miles y dos decimales. Con eso ya puedes imprimir un reporte decente sin ninguna librería.

8. Contar con booleanos

Tienes una lista de montos. Cuenta cuántos superan los S/1.000 usando el truco de sumar booleanos.

montos = [480.37, 1250.0, 95.5, 3400.2, 780.0, 1001.0]

print(sum(m > 1000 for m in montos))
3

Eso de dentro del sum es una comprensión, que vemos en el capítulo 4. Por ahora quédate con la idea: cada comparación devuelve True o False, y sumarlos cuenta los True.

9. El error de tipos, provocado

Provoca un TypeError sumando un texto y un número, y después arréglalo de dos formas distintas.

flete = '100'          # vino como texto del sistema
descuento = 50

print(int(flete) + descuento)      # los dos como numero
print(flete + str(descuento))      # los dos como texto
150
10050

Las dos son válidas y hacen cosas muy distintas. Elegir mal aquí es de donde salen los reportes con números absurdos.

10. None no es cero

Simula tres clientes donde uno no tiene fecha de última compra, y cuenta cuántos sí la tienen.

fechas = ['2025-08-22', None, '2026-01-05']

con_fecha = sum(f is not None for f in fechas)
print(f'{con_fecha} de {len(fechas)} tienen fecha')
2 de 3 tienen fecha

Este conteo es lo primero que haces al recibir cualquier archivo. En el capítulo 12 pandas te lo da en una línea, pero es exactamente la misma idea.

11. Cuáles de estas celdas están vacías de verdad

Clasifica una fila de un Excel real, donde "vacío" viene de cinco formas distintas.

celdas = {'ciudad': 'Lima', 'descuento': 0.0, 'nota': '',
          'telefono': '   ', 'satisfaccion': None, 'codigo': '0'}

for nombre, valor in celdas.items():
    print(f'{nombre:<13} {repr(valor):<8} '
          f'vacio para Python: {not valor!s:<6} '
          f'falta el dato: {valor is None}')
ciudad        'Lima'   vacio para Python: False  falta el dato: False
descuento     0.0      vacio para Python: True   falta el dato: False
nota          ''       vacio para Python: True   falta el dato: False
telefono      '   '    vacio para Python: False  falta el dato: False
satisfaccion  None     vacio para Python: True   falta el dato: True
codigo        '0'      vacio para Python: False  falta el dato: False

Fíjate en telefono y en codigo, que son los dos que mienten en direcciones opuestas 🎭

El teléfono son tres espacios: para Python tiene contenido, para ti está vacío. El código es el texto '0': para Python tiene contenido y para ti también, pero si lo conviertes a número se vuelve falso.

Por eso, con texto que viene de un Excel, el .strip() va antes de preguntar si está vacío. Siempre.

12. El promedio que se infla solo

Calcula la satisfacción promedio filtrando de las dos maneras y mira la diferencia.

notas = [5, 0, 4, None, 0, 3, 5, None, 1]

filtrado_mal = [n for n in notas if n]
filtrado_bien = [n for n in notas if n is not None]

print('respuestas contadas, mal :', len(filtrado_mal))
print('respuestas contadas, bien:', len(filtrado_bien))
print('promedio mal :', round(sum(filtrado_mal) / len(filtrado_mal), 2))
print('promedio bien:', round(sum(filtrado_bien) / len(filtrado_bien), 2))
print('inflado en   :',
      round((sum(filtrado_mal) / len(filtrado_mal))
            / (sum(filtrado_bien) / len(filtrado_bien)) * 100 - 100, 1), '%')
respuestas contadas, mal : 5
respuestas contadas, bien: 7
promedio mal : 3.6
promedio bien: 2.57
inflado en   : 40.0 %

Dos clientes pusieron cero, o sea la peor nota posible, y el primer filtro los borra del mapa 😤

El resultado es una satisfacción promedio bastante mejor de la real, calculada sobre menos gente de la que contestó. Y todo por una letra de diferencia al escribir el filtro.

13. Dos números iguales que no son el mismo

Comprueba dónde is y == se separan.

pares = [('2500', 2500), ('250', 250), ('7', 7), ('100000', 100000)]

for texto, numero in pares:
    leido = int(texto)
    print(f'{texto:>7}  ==  {leido == numero}   is  {leido is numero}')
   2500  ==  True   is  False
    250  ==  True   is  True
      7  ==  True   is  True
 100000  ==  True   is  False

Los dos de en medio dicen True y los de los extremos False, y el corte está entre 256 y 257 🚧

Ese es el rango que Python se guarda de antemano. Y lo que quiero que te lleves no es el número exacto: es que un resultado que depende de si el número es grande o pequeño no puede ser la base de nada. Con == las cuatro líneas darían True, que es lo que querías preguntar.

14. Redondear y cortar no son lo mismo

Calcula el IGV de mil facturas y suma el total de tres maneras: exacta, redondeando cada factura, y cortando los decimales de cada factura.

base = [round(3 + i * 0.7137, 3) for i in range(1000)]
con_igv = [m * 1.18 for m in base]

exacto = sum(con_igv)
redondeado = sum(round(m, 2) for m in con_igv)
truncado = sum(int(m * 100) / 100 for m in con_igv)

print('exacto     : S/', round(exacto, 2))
print('redondeando: S/', round(redondeado, 2),
      ' se desvia', round(redondeado - exacto, 2))
print('truncando  : S/', round(truncado, 2),
      ' se desvia', round(truncado - exacto, 2))
print('el truncado se come, por factura: S/',
      round((exacto - truncado) / len(base), 4))
exacto     : S/ 424201.92
redondeando: S/ 424201.91  se desvia -0.01
truncando  : S/ 424196.99  se desvia -4.93
el truncado se come, por factura: S/ 0.0049

Y aquí la sorpresa, que va en contra de lo que yo esperaba antes de medirlo 🌸

Redondear en cada factura casi no desvía nada: un céntimo en mil facturas. Porque la mitad de los redondeos suben y la otra mitad bajan, y se compensan solos.

Truncar sí desvía, y bastante: casi cinco soles en las mismas mil facturas. int(m * 100) / 100 corta los decimales, así que siempre baja, nunca sube. Medio céntimo por factura que va siempre en la misma dirección, y eso no se compensa con nada.

La lección no es "nunca redondees en medio". Es esta: lo que hace daño no es el error, es el sesgo. Un error que se reparte para los dos lados se cancela. Uno que siempre va hacia el mismo lado se acumula, factura a factura, hasta que alguien pregunta por qué el reporte no cuadra 📞

Aun así, la costumbre buena sigue siendo redondear solo al mostrar. El redondeo es una decisión de presentación, no de cálculo 🎁

Dos números iguales que Python dice que no lo son

Antes de cerrar los tipos, una que parece un detalle de nada y se lleva tardes enteras. Léela despacio, porque el código de abajo no da error: da una respuesta 🧐

La trampa

Comparas dos códigos de cliente con is, que se lee mejor que ==. Lo pruebas con los primeros del archivo y funciona.

a = int('256')
b = int('256')
print(a is b)      # True

a = int('257')
b = int('257')
print(a is b)      # False
Qué está mal

Los dos son iguales y solo uno da True 😬 is no pregunta si valen lo mismo: pregunta si son el mismo objeto en memoria. Y Python guarda cacheados los enteros del -5 al 256, así que hasta ahí coinciden por casualidad.

De 257 en adelante, dos números iguales son objetos distintos y is dice False. O sea que tu comparación funciona mientras pruebas con datos pequeños y empieza a fallar en producción, en silencio y solo con algunos clientes.

La regla no tiene excepciones: == para comparar valores, is solo con None. is None está bien porque None es único de verdad.

Comprueba que lo tienes

Lees un CSV y al sumar dos columnas te sale un TypeError. ¿Qué pasó?

  • Una de las dos es texto aunque parezca un número
  • Hay un valor nulo en medio
  • Los números son demasiado grandes
  • Falta convertir a float

Lo que te llevas

  • 🏷️ Una variable es una etiqueta pegada a un valor, y el = se lee de derecha a izquierda.
  • 🔍 Cuando algo raro pase, type() antes que nada.
  • 💸 Los decimales no son exactos: no los compares con == y redondea al final.
  • ✍️ Los métodos de texto devuelven una copia, no modifican la variable.
  • 🕳️ None es ausencia, no cero, y confundirlos te cambia los promedios.

Y si de todo el capítulo te llevas una sola frase, que sea esta:

El tipo no es un detalle del lenguaje. Es la diferencia entre sumar y pegar.

Si vienes de Excel esto ya lo sufriste: la celda que se alinea a la izquierda porque el número entró como texto. Es el mismo problema y está contado desde ahí en la guía de Excel 📊

En el capítulo 4 vamos a guardar muchas cosas juntas: listas, tuplas y diccionarios. Ahí aparece el error de copiar una lista que en realidad no se copió, que es de los más traicioneros que hay.

Que tengas lindo día! 🌸

Practica este capítulo 📓

Todo el código de arriba en un cuaderno que corre de principio a fin, y los ejercicios con una celda vacía para que los hagas tú. Se abre en Google Colab de un clic y no hay que instalar nada. Donde veas %%revisa, escribe tu respuesta y el cuaderno te dice si te salió.

¿Prefieres trabajar en tu máquina? Bájate el cuaderno de práctica o el de soluciones. Todos están también en github.com/soymissyera/MissYeraEjercicios.

¿Le sirve a alguien que conoces?

Pásale el libro. Es gratis, está entero y no pide registro 🐣

Instagram y TikTok no dejan compartir enlaces desde la web: esos dos copian la URL para que la pegues en tu historia.

¿Tienes alguna duda o consulta?