Para empezar y con un afán bastante simplificador, vamos a trabajar con dos tipos de datos básicos: números y palabras. La cosa se puede complicar eventualmente, pero por lo pronto quedémonos ahí.
Arrancamos python
desde nuestra línea de órdenes o sitio online de
prueba favorito, y vamos a ver cómo trabajar con estos datos. Ábrelo y
empieza a teclear números y palabras
>>> 3
>>> "cosas"
Las palabras llevarán comillas alrededor. Incluso aunque se trate de una sola letra. El intérprete se acuerda de lo último que has tecleado
>>> _
Podemos pasar así el día, así que vamos a empezar a hacer algo con estos números. Por ejemplo...
Nada inesperado en este área. Suma, resta, multiplicación y división
>>> 3*8+5.2**8
dará un número bastante grande, teniendo en cuenta que **
es
elevado a, es decir, 2**8
es 2 a la octava potencia. En esto no se
diferencia de otros lenguajes. Por ejemplo, si abres la consola de
desarrollo en tu navegador (con mayúsculas-control-k en Firefox, por
ejemplo), tendrás el mismo resultado, aunque estaremos trabajando en JavaScript.
Los números no son todos iguales. Los enteros y los números reales (los que tienen coma decimal) se comportarán de forma diferente, aunque no habrá que preocuparse (demasiado) por ello ahora mismo.
>>> type(3)
type(3)
<class 'int'>
>>> type(5.2)
type(5.2)
<class 'float'>
Hay una operación que es bastante peculiar de Python, la división
entera o //
>>> 800//33
800//33
24
que, precisamente, está relacionada con ese hecho. El resultado de una
división entera siempre será un entero, y los enteros o int
se
pueden usar para cosas en las que los float
no encajan. Lo que puede
tener su importancia en casos como el siguiente:
>>> type(800/20)
type(800/20)
<class 'float'>
>>> type(800//20)
type(800//20)
<class 'int'>
>>> 800/20
800/20
40.0
>>> 800//20
800//20
40
De camino,
vemos la primera función: type
. Las funciones en Python llevan
siempre paréntesis y tienen una serie de argumentos que, en su caso,
se separarán por comas.
Y también de camino, vemos el concepto
de
duck typing. Dependiendo
de la pinta que tenga lo que se ha tecleado, Python lo considerará una
cosa u otra: si anda como pato y camina como un pato, es un pato. Y si
tiene números y un . decimal, pues será un float
>>> type(333)
type(333)
<class 'int'>
>>> type(333.)
type(333.)
<class 'float'>
Cuando combinamos varias operaciones, el intérprete tiene que averiguar qué es lo que hay que aplicar primero. Los paréntesis ayudan: siempre se ejecuta primero la operación dentro de los paréntesis.
>>> 5*(3**2 + 2**3)
5*(3**2 + 2**3)
85
Pero, en ausencia de paréntesis, hay que considerar las reglas de precedencia. Tienen incluso un nemónico: Please excuse my dear aunt Sally; tomando las iniciales, paréntesis, exponentes, multiplicación, división y finalmente adición y sustracción. Por eso
5*3**2 + 2**3
ejecutará primero los exponentes, a continuación la multiplicación
dando 5x9 = 45
y finalmente las sumas. No es habitual que uno se
encuentre con operaciones demasiado complicadas salvo transcribiendo
fórmulas, pero es conveniente saberlo y en caso de duda siempre están
los paréntesis, que además hacen más legible la expresión.
Ejercicio: usando
_
para recordar el valor anterior y ↑ para repetir la última orden en el intérprete, ir calculando una docena o más de valores de una progresión aritmética o geométrica.
Los números que Python entiende son los números arábigos, vamos, los de
toda la vida. Si usamos números romanos como Ⅴ no los entenderá como
tal, sino como un carácter y nos dará un error de variable no
definida. No en todos los lenguajes es así. Perl 6 trabaja de forma
nativa con este tipo de números, y Ⅴ+5
resultará en el número 10, y
5**Ⅴ
en 3125. Los lenguajes de programación, poco a poco, van
empezando a usar el potencial completo de Unicode, pero algunos
lenguajes, como Python y JavaScript (que también dará un error)
todavía no han llegado a hacerlo.
Afortunadamente, Python no sólo trabaja con números. También puede...
Pero vamos a dar un paso hacia atrás, o hacia un lado, para reconocer que existen letras más allá de nuestro alfabeto latino. Empezando por los emojis, tales como este, ☆, y terminando con los caracteres de alfabetos vivos o muertos como este Ͳ. Un lenguaje de programación moderno, y un ordenador moderno, debe ser capaz de trabajar con todos ellos. No siempre será así, y tanto entre las dos comas anteriores como justo antes de las comillas abajo puede aparecer un espacio en blanco si el tipo de letra que se use no es capaz de acomodar el carácter Unicode correspondiente.
"þor el poderoso ✌"
Como hemos visto más arriba, las cadenas o strings están rodeadas por comillas.
Hemos elegido þ como carácter raro porque es uno de los pocos de este tipo que se pueden teclear fácilmente desde el teclado castellano. þ sale con AltGr + p. Otros caracteres son ß, que sale con AltGr + s u ø, que se obtiene con AltGr + o.
Y están compuestas por un número de caracteres
determinado, que se halla con len
>>> len(_)
len(_)
17
Las cadenas están compuestas por caracteres, y podemos acceder a ellos
indicando su índice, que comienza por 0: "þor el poderoso ✌"[16]
devolverá ✌. También podemos acceder a grupos de caracteres, usando el
rango x:y
. _[0:3]
nos devolverá los 4 primeros caracteres de la
última cadena, lo que es equivalente a _[:3]
.
Los operadores aritméticos también se pueden usar sobre cadenas.
Cuando un operador se puede aplicar sobre tipos diferentes se dice que está sobrecargado. En muchos lenguajes también puede definir el usuario sobrecargas adicionales sobre tipos definidos por él.
El +
concatenará cadenas:
>>> _[0:3]
_[0:3]
'þor'
>>> _ + " y Loki el mentiroso"
_ + " y Loki el mentiroso"
'þor y Loki el mentiroso'
y el asterisco *
, usado tradicionalmente como símbolo para
multiplicar, en este caso las replicará "þor, " * 3 + "y más þor"
resultará en la cadena 'þor, þor, þor, y más þor'
.
El tipo de estas cadenas es str
. ¿Y qué ocurre cuando tratamos de
mezclarlas con los números? Pues que resulta en un error.
Aparte de tener tipado pato, Python usa también comprobación dinámica
de tipos para saber si se puede aplicar o no una operación a sus
operandos. En este caso no encuentra ninguna forma sensata de sumar
una cadena a un número, así que simplemente expresa su disconformidad
con el asunto, diciendo que se trata de un TypeError
. Pero error es
una palabra un poco fuerte.
En el caso anterior, el intérprete nos ha dicho: TypeError: must be str, not int
. Pero es leer la palabra error y uno empieza a
sentirse culpable. Es culpa mía, todo lo hago mal, voy a empezar de
nuevo hasta que lo consiga.
Pero no hay por qué tomárselo así. Error es simplemente la forma en
la que los ordenadores nos dicen "No te he entendido bien". Los
ordenadores, y los intérpretes de lenguajes, son muy literales y todo
lo entienden tal y como se ha tecleado. Miran, y si no te entienden te
lo dicen. Pero también te dan a entender que es un problema de
expectativas. Esperaban una cosa, y ha sido otra: must be str, not int
. Debe ser un str
, no un int
. Si fueran capaces de saber de
qué cadena se trata, ellos mismos lo harían. De hecho, algunos otros
lenguajes se comportarán de forma diferente. JavaScript, por ejemplo,
dirá que "3.4"+7
es, naturalmente, 3.47
haciendo una conversión
implícita de un número a una cadena. Otro lenguaje, R, te dirá: Error in "3.4" + 7 : argumento no-numérico para operador binario
. No le
gusta la cadena y no tiene reparos en decirlo, porque R es un lenguaje
estadístico, y por tanto (casi) matemático. Perl, sin embargo, llevará
el tipado pato hasta las últimas consecuencias, dando como resultado
10.4.
Lo que viene a querer decir que lenguajes diferentes van a entender esa expresión, forzosamente ambigua, de forma diferente. Pero si no la entienden, te van a dar alguna pista de por qué no lo han hecho.
Volvamos a Python: TypeError: must be str, not int
te
dice que hay un problema con el tipo de uno de los operandos, que debe
ser una cadena (str
), no un entero. Como sólo hay un entero, el
número 7, eso quiere decir que ahí es donde está el error, al menos
según Python. De hecho, si lo hacemos al revés, 7+"3.4"
, Python nos
dirá:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
que es algo más informativo. Ya no te está diciendo que el entero es
un error, sino que alguno de los dos está equivocado. En las líneas
anteriores, además, te indica dónde ha ocurrido, aunque File "<stdin>", line 1, in <module>
no sea demasiado amigable.
En todo caso, estos mensajes te ayudan a entender dónde ha producido el malentendido y de qué se trata. Aunque estén en inglés (en la mayoría de los casos), conviene leerlos tranquilamente y comprender qué es lo que dicen, porque te da la pista de por qué el ordenador no ha sido capaz de entender lo que se le quería decir. En este caso, porque Python no sabe como sumar dos cosas que tienen un tipo diferente. Simplemente, a la siguiente, se le suministran cosas a los dos lados del signo + que sean compatibles y listos.
Y si todo falla, siempre puedes buscarlo en Internet. Eliminando lo
que sea específico de tu código, como nombres de variable y demás,
puedes
buscar el resto y
llegará, en la mayor parte de los casos,
a
StackOverflow donde
verás contextos similares y una solución al problema. En este caso, te
viene a decir que hay que hacer una conversión explícita:
7+float("3.4")
, lo que está totalmente de acuerdo
con el zen de Python:
>Explícito antes que implícito
Y, por supuesto, toda esta sección se corresponde al de
>Los errores no deben suceder en silencio
Como conclusión a esta sección: si el ordenador no te entiende y te lo dice cortésmente, lee, comprende, trata de adaptarte a lo que requiere, pero si todo falla, Google es tu amigo.
No es malo equivocarse. Sucede en las mejores familias, incluso en las operaciones más básicas. Para las cuales puedes usar Python como si fuera una calculadora un poco más complicada y que usara, además, cadenas de caracteres. Vale, una calculadora complicada y rara.