Listas¶
Las listas permiten almacenar objetos mediante un orden definido y con posibilidad de duplicados. Las listas son estructuras de datos mutables, lo que significa que podemos añadir, eliminar o modificar sus elementos. [1]
Creando listas¶
Una lista está compuesta por cero o más elementos. En Python debemos escribir estos elementos separados por comas y dentro de corchetes. Veamos algunos ejemplos de listas:
>>> empty_list = []
>>> languages = ['Python', 'Ruby', 'Javascript']
>>> fibonacci = [0, 1, 1, 2, 3, 5, 8, 13]
>>> data = ['Tenerife', {'cielo': 'limpio', 'temp': 24}, 3718, (28.2933947, -16.5226597)]
Nota
Una lista puede contener tipos de datos heterogéneos, lo que la hace una estructura de datos muy versátil.
Ejecución paso a paso a través de Python Tutor:
Advertencia
Aunque está permitido, NUNCA llames list
a una variable porque destruirías la función que nos permite crear listas. Y tampoco uses nombres derivados como _list
o list_
ya que no son nombres representativos que identifiquen el propósito de la variable.
Ejercicio
Entre en el intérprete interactivo de Python (>>>
) y cree una lista con las 5 ciudades que más le gusten.
Conversión¶
Para convertir otros tipos de datos en una lista podemos usar la función list()
:
>>> # conversión desde una cadena de texto
>>> list('Python')
['P', 'y', 't', 'h', 'o', 'n']
Si nos fijamos en lo que ha pasado, al convertir la cadena de texto Python
se ha creado una lista con 6 elementos, donde cada uno de ellos representa un carácter de la cadena. Podemos extender este comportamiento a cualquier otro tipo de datos que permita ser iterado (iterables).
Otro ejemplo interesante de conversión puede ser la de los rangos. En este caso queremos obtener una lista explícita con los valores que constituyen el rango \([0, 9]\):
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Lista vacía¶
Existe una manera particular de usar list()
y es no pasarle ningún argumento. En este caso estaremos queriendo convertir el «vacío» en una lista, con lo que obtendremos una lista vacía:
>>> list()
[]
Truco
Para crear una lista vacía, se suele recomendar el uso de []
frente a list()
, no sólo por ser más pitónico sino por tener (en promedio) un mejor rendimiento en tiempos de ejecución.
Operaciones con listas¶
Obtener un elemento¶
Igual que en el caso de las cadenas de texto, podemos obtener un elemento de una lista a través del índice (lugar) que ocupa. Veamos un ejemplo:
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> shopping[0]
'Agua'
>>> shopping[1]
'Huevos'
>>> shopping[2]
'Aceite'
>>> shopping[-1] # acceso con índice negativo
'Aceite'
El índice que usemos para acceder a los elementos de una lista tiene que estar comprendido entre los límites de la misma. Si usamos un índice antes del comienzo o después del final obtendremos un error (excepción):
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> shopping[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> shopping[-5]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Trocear una lista¶
El troceado de listas funciona de manera totalmente análoga al troceado de cadenas. Veamos algunos ejemplos:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> shopping[0:3]
['Agua', 'Huevos', 'Aceite']
>>> shopping[:3]
['Agua', 'Huevos', 'Aceite']
>>> shopping[2:4]
['Aceite', 'Sal']
>>> shopping[-1:-4:-1]
['Limón', 'Sal', 'Aceite']
>>> # Equivale a invertir la lista
>>> shopping[::-1]
['Limón', 'Sal', 'Aceite', 'Huevos', 'Agua']
En el troceado de listas, a diferencia de lo que ocurre al obtener elementos, no debemos preocuparnos por acceder a índices inválidos (fuera de rango) ya que Python los restringirá a los límites de la lista:
>>> shopping
['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> shopping[10:]
[]
>>> shopping[-100:2]
['Agua', 'Huevos']
>>> shopping[2:100]
['Aceite', 'Sal', 'Limón']
Importante
Ninguna de las operaciones anteriores modifican la lista original, simplemente devuelven una lista nueva.
Invertir una lista¶
Python nos ofrece, al menos, tres mecanismos para invertir los elementos de una lista:
- Conservando la lista original:
Opción 1: Mediante troceado de listas con step negativo:
>>> shopping ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> shopping[::-1] ['Limón', 'Sal', 'Aceite', 'Huevos', 'Agua']
Opción 2: Mediante la función
reversed()
:>>> shopping ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> list(reversed(shopping)) ['Limón', 'Sal', 'Aceite', 'Huevos', 'Agua']
- Modificando la lista original:
Utilizando la función
reverse()
(nótese que es sin «d» al final):>>> shopping ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> shopping.reverse() >>> shopping ['Limón', 'Sal', 'Aceite', 'Huevos', 'Agua']
Añadir al final de la lista¶
Una de las operaciones más utilizadas en listas es añadir elementos al final de las mismas. Para ello Python nos ofrece la función append()
. Se trata de un método «destructivo» que modifica la lista original:
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> shopping.append('Atún')
>>> shopping
['Agua', 'Huevos', 'Aceite', 'Atún']
Creando desde vacío¶
Una forma muy habitual de trabajar con listas es empezar con una vacía e ir añadiendo elementos poco a poco. Se podría hablar de un patrón creación.
Supongamos un ejemplo en el que queremos construir una lista con los números pares del \([0, 20)\):
>>> even_numbers = []
>>> for i in range(20):
... if i % 2 == 0:
... even_numbers.append(i)
...
>>> even_numbers
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Ejecución paso a paso a través de Python Tutor:
Añadir en cualquier posición de una lista¶
Ya hemos visto cómo añadir elementos al final de una lista. Sin embargo, Python ofrece una función insert()
que vendría a ser una generalización de la anterior, para incorporar elementos en cualquier posición. Simplemente debemos especificar el índice de inserción y el elemento en cuestión. También se trata de una función destructiva [2]:
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> shopping.insert(1, 'Jamón')
>>> shopping
['Agua', 'Jamón', 'Huevos', 'Aceite']
>>> shopping.insert(3, 'Queso')
>>> shopping
['Agua', 'Jamón', 'Huevos', 'Queso', 'Aceite']
Nota
El índice que especificamos en la función insert()
lo podemos intepretar como la posición delante (a la izquierda) de la cual vamos a colocar el nuevo valor en la lista.
Al igual que ocurría con el troceado de listas, en este tipo de inserciones no obtendremos un error si especificamos índices fuera de los límites de la lista. Estos se ajustarán al principio o al final en función del valor que indiquemos:
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> shopping.insert(100, 'Mermelada')
>>> shopping
['Agua', 'Huevos', 'Aceite', 'Mermelada']
>>> shopping.insert(-100, 'Arroz')
>>> shopping
['Arroz', 'Agua', 'Huevos', 'Aceite', 'Mermelada']
Consejo
Aunque es posible utilizar insert()
para añadir elementos al final de una lista, siempre se recomienda usar append()
por su mayor legibilidad:
>>> values = [1, 2, 3]
>>> values.append(4)
>>> values
[1, 2, 3, 4]
>>> values = [1, 2, 3]
>>> values.insert(len(values), 4) # don't do it!
>>> values
[1, 2, 3, 4]
Repetir elementos¶
Al igual que con las cadenas de texto, el operador *
nos permite repetir los elementos de una lista:
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> shopping * 3
['Agua',
'Huevos',
'Aceite',
'Agua',
'Huevos',
'Aceite',
'Agua',
'Huevos',
'Aceite']
Combinar listas¶
Python nos ofrece dos aproximaciones para combinar listas:
- Conservando la lista original:
Mediante el operador
+
o+=
:>>> shopping = ['Agua', 'Huevos', 'Aceite'] >>> fruitshop = ['Naranja', 'Manzana', 'Piña'] >>> shopping + fruitshop ['Agua', 'Huevos', 'Aceite', 'Naranja', 'Manzana', 'Piña']
- Modificando la lista original:
Mediante la función
extend()
:>>> shopping = ['Agua', 'Huevos', 'Aceite'] >>> fruitshop = ['Naranja', 'Manzana', 'Piña'] >>> shopping.extend(fruitshop) >>> shopping ['Agua', 'Huevos', 'Aceite', 'Naranja', 'Manzana', 'Piña']
Hay que tener en cuenta que extend()
funciona adecuadamente si pasamos una lista como argumento. En otro caso, quizás los resultados no sean los esperados. Veamos un ejemplo:
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> shopping.extend('Limón')
>>> shopping
['Agua', 'Huevos', 'Aceite', 'L', 'i', 'm', 'ó', 'n']
El motivo es que extend()
«recorre» (o itera) sobre cada uno de los elementos del objeto en cuestión. En el caso anterior, al ser una cadena de texto, está formada por caracteres. De ahí el resultado que obtenemos.
Se podría pensar en el uso de append()
para combinar listas. La realidad es que no funciona exactamente como esperamos; la segunda lista se añadiría como una sublista de la principal:
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> fruitshop = ['Naranja', 'Manzana', 'Piña']
>>> shopping.append(fruitshop)
>>> shopping
['Agua', 'Huevos', 'Aceite', ['Naranja', 'Manzana', 'Piña']]
Modificar una lista¶
Del mismo modo que se accede a un elemento utilizando su índice, también podemos modificarlo:
>>> shopping = ['Agua', 'Huevos', 'Aceite']
>>> shopping[0]
'Agua'
>>> shopping[0] = 'Jugo'
>>> shopping
['Jugo', 'Huevos', 'Aceite']
En el caso de acceder a un índice no válido de la lista, incluso para modificar, obtendremos un error:
>>> shopping[100] = 'Chocolate'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
Modificar con troceado¶
No sólo es posible modificar un elemento de cada vez, sino que podemos asignar valores a trozos de una lista:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> shopping[1:4]
['Huevos', 'Aceite', 'Sal']
>>> shopping[1:4] = ['Atún', 'Pasta']
>>> shopping
['Agua', 'Atún', 'Pasta', 'Limón']
Nota
La lista que asignamos no necesariamente debe tener la misma longitud que el trozo que sustituimos.
Borrar elementos¶
Python nos ofrece, al menos, cuatro formas para borrar elementos en una lista:
- Por su índice:
Mediante la sentencia
del
:>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> del shopping[3] >>> shopping ['Agua', 'Huevos', 'Aceite', 'Limón']
- Por su valor:
Mediante la función
remove()
:>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> shopping.remove('Sal') >>> shopping ['Agua', 'Huevos', 'Aceite', 'Limón']
Advertencia
Si existen valores duplicados, la función
remove()
sólo borrará la primera ocurrencia.- Por su índice (con extracción):
La sentencia
del
y la funciónremove()
efectivamente borran el elemento indicado de la lista, pero no «devuelven» [3] nada. Sin embargo, Python nos ofrece la funciónpop()
que además de borrar, nos «recupera» el elemento; algo así como una extracción. Lo podemos ver como una combinación de acceso + borrado:>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> product = shopping.pop() # shopping.pop(-1) >>> product 'Limón' >>> shopping ['Agua', 'Huevos', 'Aceite', 'Sal'] >>> product = shopping.pop(2) >>> product 'Aceite' >>> shopping ['Agua', 'Huevos', 'Sal']
Nota
Si usamos la función
pop()
sin pasarle ningún argumento, por defecto usará el índice -1, es decir, el último elemento de la lista. Pero también podemos indicarle el índice del elemento a extraer.- Por su rango:
Mediante troceado de listas:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> shopping[1:4] = [] >>> shopping ['Agua', 'Limón']
Borrado completo de la lista¶
Python nos ofrece, al menos, dos formas para borrar una lista por completo:
Utilizando la función
clear()
:>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> shopping.clear() # Borrado in-situ >>> shopping []
«Reinicializando» la lista a vacío con
[]
:>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> shopping = [] # Nueva zona de memoria >>> shopping []
La diferencia entre ambos métodos tiene que ver con cuestiones internas de gestión de memoria y de rendimiento:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> id(shopping)
4416018560
>>> shopping.clear()
>>> id(shopping) # se mantiene la misma "posición de memoria"
4416018560
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> id(shopping)
4458688576
>>> shopping = []
>>> id(shopping) # se crea una nueva "posición de memoria"
4458851520
Ver también
La memoria que queda «en el limbo» después de asignar un nuevo valor a la lista es detectada por el recolector de basura de Python, quien se encarga de liberar aquellos datos que no están referenciados por ninguna variable.
A efectos de velocidad de ejecución, shopping.clear()
«parece» ir más rápido que shopping = []
.
Encontrar un elemento¶
Si queremos descubrir el índice que corresponde a un determinado valor dentro la lista podemos usar la función index()
para ello:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> shopping.index('Huevos')
1
Tener en cuenta que si el elemento que buscamos no está en la lista, obtendremos un error:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> shopping.index('Pollo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 'Pollo' is not in list
Nota
Si buscamos un valor que existe más de una vez en una lista, la función index()
sólo nos devolverá el índice de la primera ocurrencia.
Advertencia
En listas no disponemos de la función find()
que sí estaba disponible para cadenas de texto.
Pertenencia de un elemento¶
Si queremos comprobar la existencia de un determinado elemento en una lista, podríamos buscar su índice, pero la forma pitónica de hacerlo es utilizar el operador in
:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> 'Aceite' in shopping
True
>>> 'Pollo' in shopping
False
Nota
El operador in
siempre devuelve un valor booleano, es decir, verdadero o falso.
Ejercicio
pypas: isogram
Número de ocurrencias¶
Para contar cuántas veces aparece un determinado valor dentro de una lista podemos usar la función count()
:
>>> sheldon_greeting = ['Penny', 'Penny', 'Penny']
>>> sheldon_greeting.count('Howard')
0
>>> sheldon_greeting.count('Penny')
3
Dividir una cadena de texto en lista¶
Una tarea muy común al trabajar con cadenas de texto es dividirlas por algún tipo de separador. En este sentido, Python nos ofrece la función split()
, que debemos usar anteponiendo el «string» que queramos dividir:
>>> proverb = 'No hay mal que por bien no venga'
>>> proverb.split()
['No', 'hay', 'mal', 'que', 'por', 'bien', 'no', 'venga']
>>> tools = 'Martillo,Sierra,Destornillador'
>>> tools.split(',')
['Martillo', 'Sierra', 'Destornillador']
Nota
Si no se especifica un separador, split()
usa por defecto cualquier secuencia de espacios en blanco, tabuladores y saltos de línea.
La función split()
devuelve una lista donde cada elemento es una parte de la cadena de texto original:
>>> game = 'piedra-papel-tijera'
>>> type(game_tools := game.split('-'))
list
>>> game_tools
['piedra', 'papel', 'tijera']
Ejercicio
pypas: num-words
Particionado de cadenas de texto¶
Existe una forma algo más «elaborada» de dividir una cadena a través del particionado. Para ello podemos valernos de la función partition()
que proporciona Python.
Esta función toma un argumento como separador, y divide la cadena de texto en 3 partes: lo que queda a la izquierda del separador, el separador en sí mismo y lo que queda a la derecha del separador:
>>> text = '3 + 4'
>>> text.partition('+')
('3 ', '+', ' 4')
Ver también
En este caso el resultado de la función partition()
es una tupla.
Unir una lista en cadena de texto¶
Dada una lista, podemos convetirla a una cadena de texto, uniendo todos sus elementos mediante algún separador. Para ello hacemos uso de la función join()
con la siguiente estructura:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> ','.join(shopping)
'Agua,Huevos,Aceite,Sal,Limón'
>>> ' '.join(shopping)
'Agua Huevos Aceite Sal Limón'
>>> '|'.join(shopping)
'Agua|Huevos|Aceite|Sal|Limón'
Hay que tener en cuenta que join()
sólo funciona si todos sus elementos son cadenas de texto:
>>> ', '.join([1, 2, 3, 4, 5])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected str instance, int found
Truco
Esta función join()
es realmente la opuesta a la función split()
.
Ejercicio
pypas: fix-date
Ordenar una lista¶
Python proporciona, al menos, dos formas de ordenar los elementos de una lista:
- Conservando lista original:
Mediante la función
sorted()
que devuelve una nueva lista ordenada:>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> sorted(shopping) ['Aceite', 'Agua', 'Huevos', 'Limón', 'Sal']
- Modificando la lista original:
Mediante la función
sort()
:>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón'] >>> shopping.sort() >>> shopping ['Aceite', 'Agua', 'Huevos', 'Limón', 'Sal']
Ambos métodos admiten un parámetro «booleano» reverse
para indicar si queremos que la ordenación se haga en sentido inverso:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> sorted(shopping, reverse=True)
['Sal', 'Limón', 'Huevos', 'Agua', 'Aceite']
Longitud de una lista¶
Podemos conocer el número de elementos que tiene una lista con la función len()
:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> len(shopping)
5
Iterar sobre una lista¶
Al igual que hemos visto con las cadenas de texto, también podemos iterar sobre los elementos de una lista utilizando la sentencia for
:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> for product in shopping:
... print(product)
...
Agua
Huevos
Aceite
Sal
Limón
Nota
También es posible usar la sentencia break
en este tipo de bucles para abortar su ejecución en algún momento que nos interese.
Ejercicio
pypas: chars-list
Iterar usando enumeración¶
Hay veces que no sólo nos interesa «visitar» cada uno de los elementos de una lista, sino que también queremos saber su índice dentro de la misma. Para ello Python nos ofrece la función enumerate()
:
>>> shopping = ['Agua', 'Huevos', 'Aceite', 'Sal', 'Limón']
>>> for i, product in enumerate(shopping):
... print(i, product)
...
0 Agua
1 Huevos
2 Aceite
3 Sal
4 Limón
Ejecución paso a paso a través de Python Tutor:
Truco
Es posible utilizar el parámetro start
con enumerate()
para indicar el índice en el que queremos comenzar. Por defecto es 0.
Iterar sobre múltiples listas¶
Python ofrece la posibilidad de iterar sobre múltiples listas en paralelo utilizando la función zip()
. Se basa en ir «juntando» ambas listas elemento a elemento:
Veamos un ejemplo en el que añadimos ciertos detalles a nuestra lista de la compra:
>>> shopping = ['Agua', 'Aceite', 'Arroz']
>>> details = ['mineral natural', 'de oliva virgen', 'basmati']
>>> for product, detail in zip(shopping, details):
... print(product, detail)
...
Agua mineral natural
Aceite de oliva virgen
Arroz basmati
Ejecución paso a paso a través de Python Tutor:
Nota
En el caso de que las listas no tengan la misma longitud, la función zip()
realiza la combinación hasta que se agota la lista más corta.
Dado que zip()
produce un iterador, si queremos obtener una lista explícita con la combinación en paralelo de las listas, debemos construir dicha lista de la siguiente manera:
>>> shopping = ['Agua', 'Aceite', 'Arroz']
>>> details = ['mineral natural', 'de oliva virgen', 'basmati']
>>> list(zip(shopping, details))
[('Agua', 'mineral natural'),
('Aceite', 'de oliva virgen'),
('Arroz', 'basmati')]
Ejercicio
pypas: dot-product
Comparar listas¶
Supongamos este ejemplo:
>>> [1, 2, 3] < [1, 2, 4]
True
Python llega a la conclusión de que la lista [1, 2, 3]
es menor que [1, 2, 4]
porque va comparando elemento a elemento:
El
1
es igual en ambas listas.El
2
es igual en ambas litas.El
3
es menor que el4
, por lo que la primera lista es menor que la segunda.
Entender la forma en la que se comparan dos listas es importante para poder aplicar otras funciones y obtener los resultados deseados.
Ver también
Esta comparación funciona de forma totalmente análoga a la comparación de cadenas de texto.
Cuidado con las copias¶
Las listas son estructuras de datos mutables y esta característica nos obliga a tener cuidado cuando realizamos copias de listas, ya que la modificación de una de ellas puede afectar a la otra.
Veamos un ejemplo sencillo:
>>> original_list = [4, 3, 7, 1]
>>> copy_list = original_list
>>> original_list[0] = 15
>>> original_list
[15, 3, 7, 1]
>>> copy_list
[15, 3, 7, 1]
Ejecución paso a paso a través de Python Tutor:
Nota
A través de Python Tutor se puede ver claramente el motivo de por qué ocurre esto. Dado que las variables «apuntan» a la misma zona de memoria, al modificar una de ellas, el cambio también se ve reflejado en la otra.
Una posible solución a este problema es hacer una «copia dura». Para ello Python proporciona la función copy()
:
>>> original_list = [4, 3, 7, 1]
>>> copy_list = original_list.copy()
>>> original_list[0] = 15
>>> original_list
[15, 3, 7, 1]
>>> copy_list
[4, 3, 7, 1]
Ejecución paso a paso a través de Python Tutor:
Existe otra aproximación a este problema, y es utilizar un troceado completo de la lista, lo que nos devuelve una «copia desvinculada» de manera implícita:
>>> original_list = [4, 3, 7, 1]
>>> copy_list = original_list[:]
>>> id(original_list) != id(copy_list)
True
Truco
En el caso de que estemos trabajando con listas que contienen elementos mutables, debemos hacer uso de la función deepcopy()
dentro del módulo copy
de la librería estándar.
Veracidad múltiple¶
Si bien podemos usar sentencias condicionales para comprobar la veracidad de determinadas expresiones, Python nos ofrece dos funciones «built-in» con las que podemos evaluar si se cumplen todas las condiciones all()
o si se cumple alguna condición any()
. Estas funciones trabajan sobre iterables, y el caso más evidente es una lista.
Supongamos un ejemplo en el que queremos comprobar si una determinada palabra cumple las siguientes condiciones:
Su longitud total es mayor que 4.
Empieza por «p».
Contiene, al menos, una «y».
Veamos la versión clásica:
>>> word = 'python'
>>> if len(word) > 4 and word.startswith('p') and word.count('y') >= 1:
... print('Cool word!')
... else:
... print('No thanks')
...
Cool word!
Veamos la versión con veracidad múltiple usando all()
, donde se comprueba que se cumplan todas las expresiones:
>>> word = 'python'
>>> enough_length = len(word) > 4 # True
>>> right_beginning = word.startswith('p') # True
>>> min_ys = word.count('y') >= 1 # True
>>> is_cool_word = all([enough_length, right_beginning, min_ys])
>>> if is_cool_word:
... print('Cool word!')
... else:
... print('No thanks')
...
Cool word!
Veamos la versión con veracidad múltiple usando any()
, donde se comprueba que se cumpla alguna expresión:
>>> word = 'yeah'
>>> enough_length = len(word) > 4 # False
>>> right_beginning = word.startswith('p') # False
>>> min_ys = word.count('y') >= 1 # True
>>> is_fine_word = any([enough_length, right_beginning, min_ys])
>>> if is_fine_word:
... print('Fine word!')
... else:
... print('No thanks')
...
Fine word!
Consejo
Este enfoque puede ser interesante cuando se manejan muchas condiciones o bien cuando queremos separar las condiciones y agruparlas en una única lista.
A tener en cuenta la peculiaridad de estas funciones cuando trabajan con la lista vacía:
>>> all([])
True
>>> any([])
False
Listas por comprensión¶
Las listas por comprensión establecen una técnica para crear listas de forma más compacta basándose en el concepto matemático de conjuntos definidos por comprensión.
Podríamos decir que su sintaxis sigue un modelo VLC (Value-Loop-Condition) tal y como se muestra en la siguiente figura:
En primer lugar veamos un ejemplo en el que convertimos una cadena de texto con valores numéricos en una lista con los mismos valores pero convertidos a enteros. En su versión clásica haríamos algo tal que así:
>>> values = '32,45,11,87,20,48'
>>> int_values = []
>>> for value in values.split(','):
... int_value = int(value)
... int_values.append(int_value)
...
>>> int_values
[32, 45, 11, 87, 20, 48]
Ahora veamos el código utilizando una lista por comprensión:
>>> values = '32,45,11,87,20,48'
>>> int_values = [int(value) for value in values.split(',')]
>>> int_values
[32, 45, 11, 87, 20, 48]
Condiciones en comprensiones¶
También existe la posibilidad de incluir condiciones en las listas por comprensión.
Continuando con el ejemplo anterior, supongamos que sólo queremos crear la lista con aquellos valores que empiecen por el dígito 4:
>>> values = '32,45,11,87,20,48'
>>> int_values = [int(v) for v in values.split(',') if v.startswith('4')]
>>> int_values
[45, 48]
Anidamiento en comprensiones¶
En la iteración que usamos dentro de la lista por comprensión es posible usar bucles anidados.
Veamos un ejemplo en el que generamos todas las combinaciones de una serie de valores:
>>> values = '32,45,11,87,20,48'
>>> svalues = values.split(',')
>>> combinations = [f'{v1}x{v2}' for v1 in svalues for v2 in svalues]
>>> combinations
['32x32',
'32x45',
'32x11',
'32x87',
'32x20',
'32x48',
'45x32',
'45x45',
...
'48x45',
'48x11',
'48x87',
'48x20',
'48x48']
Consejo
Las listas por comprensión son una herramienta muy potente y nos ayuda en muchas ocasiones, pero hay que tener cuidado de no generar expresiones excesivamente complejas. En estos casos es mejor una aproximación clásica.
Ejercicio
pypas: fcomp
sys.argv
¶
Cuando queramos ejecutar un programa Python desde línea de comandos, tendremos la posibilidad de acceder a los argumentos de dicho programa. Para ello se utiliza una lista «especial» que la encontramos dentro del módulo sys
y que se denomina argv
:
Veamos una aplicación de lo anterior en un programa que convierte un número decimal a una determinada base, ambos argumentos pasados por línea de comandos:
1import sys
2
3number = int(sys.argv[1])
4tobase = int(sys.argv[2])
5
6match tobase:
7 case 2:
8 result = f'{number:b}'
9 case 8:
10 result = f'{number:o}'
11 case 16:
12 result = f'{number:x}'
13 case _:
14 result = None
15
16if result is None:
17 print(f'Base {tobase} not implemented!')
18else:
19 print(result)
Si lo ejecutamos obtenemos lo siguiente:
$ python dec2base.py 65535 2
1111111111111111
Funciones matemáticas¶
Python nos ofrece, entre otras [4], estas tres funciones matemáticas básicas que se pueden aplicar sobre listas.
- Suma de todos los valores:
Mediante la función
sum()
:>>> data = [5, 3, 2, 8, 9, 1] >>> sum(data) 28
- Mínimo de todos los valores:
Mediante la función
min()
:>>> data = [5, 3, 2, 8, 9, 1] >>> min(data) 1
- Máximo de todos los valores:
Mediante la función
max()
:>>> data = [5, 3, 2, 8, 9, 1] >>> max(data) 9
Ejercicio
Lea desde línea de comandos una serie de números y obtenga la media de dichos valores (redondeando a 2 cifras decimales).
La llamada se haría de la siguiente manera:
$ python avg.py 32 56 21 99 12 21
Plantilla de código para el programa:
import sys
# En values tendremos una lista con los valores (como strings)
values = sys.argv[1:]
# Su código debajo de aquí
- Ejemplo
Entrada:
32 56 21 99 12 17
Salida:
40.17
Solución: avg.py
Listas de listas¶
Como ya hemos visto en varias ocasiones, las listas son estructuras de datos que pueden contener elementos heterogéneos. Estos elementos pueden ser a su vez listas.
A continuación planteamos un ejemplo del contexto deportivo. Un equipo de fútbol suele tener una disposición en el campo organizada en líneas de jugadores/as. En aquella alineación con la que España ganó la copa del mundo en 2023 había una disposición 4-3-3 con las siguientes jugadoras:
Veamos una posible representación de este equipo de fútbol usando una lista compuesta de listas. Primero definimos cada una de las líneas:
>>> goalkeeper = 'Cata'
>>> defenders = ['Olga', 'Laia', 'Irene', 'Ona']
>>> midfielders = ['Jenni', 'Teresa', 'Aitana']
>>> forwards = ['Mariona', 'Salma', 'Alba']
Y ahora las juntamos en una única lista:
>>> team = [goalkeeper, defenders, midfielders, forwards]
>>> team
['Cata',
['Olga', 'Laia', 'Irene', 'Ona'],
['Jenni', 'Teresa', 'Aitana'],
['Mariona', 'Salma', 'Alba']]
Podemos comprobar el acceso a distintos elementos:
>>> team[0] # portera
'Cata'
>>> team[1][0] # lateral izquierdo
'Olga'
>>> team[2] # centrocampistas
['Jenni', 'Teresa', 'Aitana']
>>> team[3][1] # delantera centro
'Salma'
También podemos recorrer toda la alineación:
>>> for playline in team:
... if isinstance(playline, list):
... for player in playline:
... print(player, end=' ')
... print()
... else:
... print(playline)
...
Cata
Olga Laia Irene Ona
Jenni Teresa Aitana
Mariona Salma Alba
Ejercicio
pypas: mulmatrix2
Ejercicios¶
pypas: max-value
pypas: max-value-with-min
pypas: min-value
pypas: min-value-with-max
pypas: remove-dups
pypas: flatten-list
pypas: remove-consecutive-dups
pypas: all-same
pypas: sum-diagonal
pypas: powers2
pypas: dec2bin
pypas: sum-mixed
pypas: n-multiples
pypas: drop-even
pypas: nth-power
pypas: name-initials
pypas: non-consecutive
pypas: mult-reduce
pypas: digit-rev-list
pypas: time-plus-minutes
pypas: add-positives
pypas: add-opposites
pypas: descending-numbers
pypas: merge-sorted
pypas: trimmed-add
pypas: wolves
pypas: minmax
pypas: cascading-subsets
pypas: diff-cuboid
pypas: fl-strip
pypas: logical-chain
pypas: first-unused-id
pypas: find-odds
pypas: chemistry
pypas: next-next
pypas: v-partition
pypas: attach-len
pypas: reversing-words
pypas: barycenter
pypas: sort-custom
pypas: flatten-list-deep
pypas: first-duplicated
pypas: fill-values
pypas: frange
pypas: qual-number
pypas: mul-matrix