Más sobre colecciones

Ahora que ya tenemos un conocimento más amplio sobre las cuestiones fundamentales del lenguaje, veamos otras propiedades de las colecciones.

«Slicing»

Las listas, tuplas y cadenas soportan una propiedad llamada slicing. No hay un concepto en español que haya ocupado definitivamente su lugar, así que mantendremos el término original. Se trata de una funcionalidad de las colecciones ordenadas que nos permite acceder a un subconjunto de ellas. Consideremos la siguiente lista.

>>> lenguajes = ["Python", "C", "C++", "Java", "Elixir"]

Usando la nomenclatura coleccion[inicio:fin], podemos obtener una porción de ella según los límites indicados.

# Obtiene desde el segundo elemento (índice 1) inclusive hasta el cuarto.
>>> lenguajes[1:4]
['C', 'C++', 'Java']

Si inicio o fin están ausentes, por defecto serán 0 y len(coleccion) (es decir, todos los elementos de la colección), respectivamente.

>>> lenguajes[1:]
['C', 'C++', 'Java', 'Elixir']
>>> lenguajes[1:len(lenguajes)]
['C', 'C++', 'Java', 'Elixir']
>>> lenguajes[:4]
['Python', 'C', 'C++', 'Java']
>>> lenguajes[0:4]
['Python', 'C', 'C++', 'Java']
>>> lenguajes[:]
['Python', 'C', 'C++', 'Java', 'Elixir']
>>> lenguajes[0:len(lenguajes)]
['Python', 'C', 'C++', 'Java', 'Elixir']

El segundo indicador (fin) puede ser un número negativo, lo cual comienza la cuenta desde el final de la colección.

# Todos los elementos a excepción del último.
>>> lenguajes[:-1]
['Python', 'C', 'C++', 'Java']

Un tercer número indica el intervalo según el cual se obtienen elementos de la colección (1 por defecto).

>>> lenguajes[::2]
['Python', 'C++', 'Elixir']
>>> lenguajes[1:-1:2]
['C', 'Java']

Si el intervalo es negativo, los elementos se empiezan a obtener en modo inverso, de modo que coleccion[::-1] retorna todos sus elementos al revés.

>>> lenguajes[::-1]
['Elixir', 'Java', 'C++', 'C', 'Python']

Como mencionamos al principio, estas propiedades son también aplicables a tuplas y cadenas, del mismo modo.

>>> s = "¡Hola, mundo!"
>>> s[1::2]
'Hl,mno'
>>> s[::-1]
'!odnum ,aloH¡'

«Unpacking»

La traducción más fiel para este concepto sería desempaquetamiento, si se nos permite el neologismo. La propiedad de unpacking nos permite "desempaquetar" los elementos de una colección en variables individuales.

>>> t = (1, 2, 3)
>>> a, b, c = t
>>> a
1
>>> b
2
>>> c
3

¡Sencillo! Si no ha quedado lo suficientemente claro, el código anterior es similar al siguiente.

>>> t = (1, 2, 3)
>>> a = t[0]
>>> b = t[1]
>>> c = t[2]

Para que esta operación no arroje un error, el número de objetos separados por comas a la izquierda del signo igual debe coincidir con el número de elementos dentro de la colección a la derecha. Aunque vía slicing podemos, por ejemplo, desempaquetar los primeros dos elementos.

>>> a, b = t[:2]

O bien los últimos dos.

>>> b, c = t[-2:]

Esta propiedad de las colecciones ordenadas nos permitirá hablar de una última cosa.

Enumerando colecciones

Python incluye una función llamada enumerate(), que obtiene como argumento una colección y retorna sus elementos enumerados, como se observa a continuación.

>>> lenguajes = ["Python", "C", "C++", "Java"]
>>> list(enumerate(lenguajes))
[(0, 'Python'), (1, 'C'), (2, 'C++'), (3, 'Java')]

(enumerate() opera del mismo modo que range(), en el sentido que no retorna una lista sino un objeto iterable cuyos elementos son generados al tiempo en que son utilizados, para optimizar el rendimiento del código. Por ello, para ver todos sus elementos al mismo tiempo, es necesario convertirlo a una lista).

El valor de retorno es un iterable cuyos elementos son tuplas, dentro de las cuales el primer elemento indica la posición del segundo en la colección pasada como argumento.

Ahora bien, esto es sumamente útil cuando, al recorrer una colección con un bucle for, estamos interesados tanto en los elementos como en sus posiciones.

>>> for i, lenguaje in enumerate(lenguajes):
...     print(i, lenguaje)
...
0 Python
1 C
2 C++
3 Java

Lo cual es mucho más pythonico y rápido que:

# ¡¡¡Menos legible y más lento!!!
>>> for i in range(len(lenguajes)):
...     print(i, lenguajes[i])
...
0 Python
1 C
2 C++
3 Java

Bien, considero hasta aquí suficiente este apéndice sobre colecciones. Avancemos ahora hacia las operaciones de entrada y salida de archivos que, seguramente, utilizarás en algún momento.