Variables

En Python las variables se definen de forma implícita, es decir, no es necesario declararlas. La variable tendrá el tipo del valor al que hace referencia, y eso puede cambiar en cualquier momento.


In [13]:
a = "hello"
a


Out[13]:
'hello'

In [14]:
a = 3
a


Out[14]:
3

Aunque también es posible difinir una variable usando un tipo concreto no es muy habitual verlo en código de producción.


In [15]:
a = str()
a


Out[15]:
''

IMPORTANTE: Elegir nombres descriptivos para las variables es crítico. En este documento se utilizan a veces nombres de variables sin significado porque son ejemplos muy simples (sin relación con un problema concreto). En un programa real deben utilizarse siempre conceptos del dominio de la aplicación. (http://www.itiseezee.com/?p=83)

Tipos básicos

Python dispone de los tipos de datos habituales en cualquier lenguaje de programación moderno.

Enteros

El entero (int) es el tipo más simple en la mayoría de los lenguajes. Como cualquier otro tipo, es posible crear un nuevo entero a partir de un literal.


In [16]:
num = 42
num


Out[16]:
42

En el caso de Python, el entero tiene una peculiaridad: no tiene límite, puede ser arbitrariamente largo.


In [17]:
big_number = 100 ** 100
big_number


Out[17]:
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L

Efectivamente, el operador ** es la potencia. Por supuesto, los enteros de Python disponen de todos los operadores habituales: suma, resta, múltiplicación, división, división entera y módulo. Y también operadores a nivel de bits como and, or y desplazamientos:


In [18]:
a = 32 + 16
a


Out[18]:
48

In [19]:
3.2//2


Out[19]:
1.0

In [20]:
a | 4


Out[20]:
52

In [21]:
a & 31


Out[21]:
16

In [22]:
a >> 2


Out[22]:
12

A pesar de las apariencias, el listado anterior es una serie de invocaciones a métodos, porque como se ha dicho, los enteros también son objetos:


In [23]:
a = 3
a.__add__(4)


Out[23]:
7

Esto es porque Python permite realizar sobrecarga de operadores, es decir, el lenguaje permite crear tipos (clases) que definen el significado de los operadores. Esto se realiza por medio de métodos especiales (como el __add__ del listado anterior). Volveremos con este tema más adelante.

Flotantes

El otro tipo de dato numérico esencial es el flotante (float). Como en el caso del entero, el float de Python tiene precisión y tamaño arbitrário, lo cual simplifica mucho las cosas cuando se requieren número muy grandes. Para definir una variable de tipo float, basta como siempre, asignar un literal:


In [24]:
size = 3.4
size


Out[24]:
3.4

Los operadores de Python hacen promoción automática de tipos cuando se operan por ejemplo enteros con flotantes:


In [25]:
4 * 4.2


Out[25]:
16.8

Eso no significa que esté permitido aplicar cualquier operador a cualquier pareja de operandos. Python a pesar de ser dinámico es un lenguaje fuertemente tipado:


In [26]:
"hello" + 3.2


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-26-73d5a9e04006> in <module>()
----> 1 "hello" + 3.2

TypeError: cannot concatenate 'str' and 'float' objects

Aunque el operador de suma está de hecho definido para las cadenas su significado es la concatenación como se puede ver en el mensaje de error.

Complejos

Python es uno de los pocos lenguajes de propósito general que dispone de números complejos como un tipo «empotrado» (builtin) y su uso es absolutamente equivalente a los enteros o flotantes:


In [ ]:
n = 3 + 4j
n * 2

In [ ]:
n.imag

In [ ]:
abs(n)

In [ ]:
type(n)

In [ ]:
1j * 1j

Booleanos

El booleano (bool) solo puede tener dos valores True y False (con esa capitalización concreta).


In [ ]:
b1 = True

Soporta los operadores clásicos: and, or y not:


In [ ]:
not b1

In [ ]:
b1 and False

In [ ]:
b1 or False

Como ocurre en C, cualquier expresión genera (o puede convertirse) a un valor lógico, lo que resulta muy útil y permite simplificar el código en muchos casos:


In [ ]:
3 > 5

In [ ]:
bool(3.7)

El 0 (entero, flotante o complejo) se evalúa como falso. Las secuencias vacías, incluidas las cadenas también se consideran False.


In [27]:
bool("")


Out[27]:
False

Las operaciones and y or tienen un tratamiento interesante de sus operandos. La operación and realmente no devuelve un booleano. Es su lugar devuelve el primer operando que se evalúe como falso, y los demás no llegan a ejecutarse nunca:


In [30]:
4 and (2 -2) and (5 - 3)


Out[30]:
0

El 0 que devuelve la sentencia es el resultado de la operación 2 - 2, y la operación 5 - 3 no se ha ejecutado. La operación or realiza algo similar. Devuelve el primer valor que se evalúe como cierto, y no evalúa ningún operando más.


In [31]:
2 > 3 or 2 + 3 or 3 - 1


Out[31]:
5

Python evalúa 2 > 3 (que es falso), después evalúa 2 + 3, y como es cierto (distinto de cero), lo devuelve sin ejecutar nada más.

None

Es un valor nulo (de tipo NoneType), que como su nombre indica, se utilizar para indicar que una variable no tiene valor. Se puede utilizar como un valor literal en cualquier expresión y se evalúa como Falso en la operaciones lógicas:


In [32]:
a = "example"
a = None
bool(a)


Out[32]:
False

Operadores y precedencia

Hay una relaciónd de precedencia (una prioridad) cuando se evalúan expresiones aritméticas o lógicas en un programa.


In [33]:
2 + 3 * 4


Out[33]:
14

Para modificar las reglas de precedencia se pueden utilizar paréntesis:


In [34]:
(2 + 3) * 4


Out[34]:
20

Como se puede comprobar, la multiplicación tiene prioridad sobre la suma. En concreto, las reglas para los operadores matemáticos son:

Operador Significado
\*\* potencia
+ y - (un operando) signo del valor
\*, / y % (dos operandos) multiplicación, división y módulo
+ y - (dos operandos) suma y resta

En caso de la más mínima duda, mejor poner paréntesis.

Contenedores

Las contenedores de Python son aquellos tipos de datos que permiten grupos valores. Todos permiten almacenar valores de tipos diferentes en el mismo contenedor de forma directa. Todos los contenedores son indexables, y eso es mucho decir en el caso de Python. En este momento se muestran los más sencillos: cadenas, listas, tuplas, diccionarios y conjuntos.

Desde el punto de vista lógico, todas los contenedores se evalúan como falso cuando están vacíos.

Cadenas (str)

En el primer ejemplo ya se ha visto la cadena "Hello World" y el resultado de invocar tu método lower(). Las cadenas se delimitan con comillas simples (') o dobles (") indistintamente, siempre que estén correctamente pareados:


In [35]:
what = "Hello"
who = 'World'
what + ' ' + who


Out[35]:
'Hello World'

Como se puede apreciar en ese ejemplo, soportan el operador de concatenación. También el de multiplicación (siempre que sea con un entero):


In [36]:
"hello " * 3


Out[36]:
'hello hello hello '

Indexación y slicing

Y la indexación por suspuesto es una operación básica:


In [37]:
what[0]


Out[37]:
'H'

Como en muchos lenguajes, el primer elemento corresponde con el índice 0. Pero también permite indexar desde el final si el indice es negativo (realmente muy útil!).


In [42]:
what[-1]


Out[42]:
'o'

Algo no tan común es el slicing, que permite indicar un rango mediante dos índices separados por ':':


In [43]:
who[1:4]


Out[43]:
'orl'

In [44]:
who[-4:-1]


Out[44]:
'orl'

Además, los indices son opcionales si corresponden con el principio y final respectivamente.


In [45]:
who[:4]


Out[45]:
'Worl'

In [ ]:
who[2:]

Un tercer índice permite además indicar un "paso", es decir, la cantidad de elementos que debe saltar. Y ese paso puede ser negativo.


In [46]:
(what + who)[2:9:2]


Out[46]:
'lool'

In [47]:
(what + who)[::-1]


Out[47]:
'dlroWolleH'

Las cadenas son tipos inmutables, es decir, no se puede modificar su valor:


In [48]:
who[2] = "K"


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-48-cb3eb96f633e> in <module>()
----> 1 who[2] = "K"

TypeError: 'str' object does not support item assignment

Tuplas (tuple)

Las tuplas son agrupaciones de valores de tipos cualesquiera. Se representan como una secuencia entre paréntesis con los valores separados por comas:


In [49]:
t1 = (1, "a", 3.2)

Son indexables igual que las cadenas y soportan los mismo operadores de slicing, y también son inmutables.


In [50]:
t1[1]


Out[50]:
'a'

Se pueden crear a partir de varias variables independientes (empaquetar):


In [51]:
text = "hi"
num = 42
t2 = text, num
t2


Out[51]:
('hi', 42)

Y también obtener los valores por separado (desempaquetar). Esto es interesante porque gracias a las tuplas, las funciones Python pueden devolver varios valores:


In [52]:
a, b = t2
a


Out[52]:
'hi'

Listas (list)

Las listas son muy similares a las tuplas. Las listas se representan mediante valores entre corchetes. La diferencia más importante es que las listas son mutables:


In [53]:
x = ["hi", 3, 1j]
x[1] = "other"
x


Out[53]:
['hi', 'other', 1j]

In [54]:
x.append(1000.)
x


Out[54]:
['hi', 'other', 1j, 1000.0]

Diccionarios (dict)

Los tablas asociativas, similars a los hash-maps de otros lenguajes. Tanto las claves como los vallores pueden ser de cualquier tipo. La única limitación es que el tipo de la clave debe ser hashable. Los diccionarios se representan como pares clave:valor entre corchetes.


In [55]:
sizes = {"big":100, "medium":50, "small":10, 3: 10}
sizes["big"]


Out[55]:
100

Los diccionares también son mutables e iterables (por claves), pero no permiten hacer slicing:


In [56]:
for key in sizes:
    print(key)


small
big
medium
3

In [57]:
sizes["big"] = 200
sizes


Out[57]:
{3: 10, 'big': 200, 'medium': 50, 'small': 10}

Conjuntos (set)

Los conjuntos son agrupaciones de valores de tipos cualesquiera sin ningún criterio de orden. El conjunto no puede contener dos valores que sean considerados equivalentes. Se representa como una secuencias de valores entre llaves.


In [58]:
s = set()
s.add("letter")
s.add(4.0)
s


Out[58]:
{4.0, 'letter'}

El conjunto soporta las típicas operaciones algebráicas como unión, intersección, diferencia, etc.


In [59]:
set([1, 2]).union(set([2, 3]))


Out[59]:
{1, 2, 3}

In [60]:
set([1, 2]).intersection(set([2, 3]))


Out[60]:
{2}

In [61]:
set([1, 2]).difference(set([2, 3]))


Out[61]:
{1}