Una list es una colección mutable de elementos en secuencia.
Como la mayoría de las colecciones (consulta los tipos integrados tuple, dict y set), las listas pueden contener referencias a cualquier tipo (o varios tipos) de datos, incluidas otras listas.
Como en cualquier secuencia, se puede acceder a los elementos mediante un 0-based index desde la izquierda y un -1-based index desde la derecha.
Las listas se pueden copiar total o parcialmente mediante la notación de slices o <list>.copy().
Las listas admiten tanto las operaciones de secuencia comunes como las mutables, por ejemplo min()/max(), <list>.index(), <list>.append() y <list>.reverse().
Se puede iterar sobre los elementos de una lista con la construcción for item in <list>.
for index, item in enumerate(<list>) se puede usar cuando se necesitan tanto el índice del elemento como su valor.
Internamente, las lists se implementan como arrays dinámicos, similares al tipo ArrayList de Java, y se usan con mayor frecuencia para almacenar grupos de datos similares (strings, números, sets, etc.) de longitud desconocida.
Las listas son una estructura de datos sumamente flexible y útil, y muchos de los métodos y operaciones integrados de Python producen listas como resultado.
Una list se puede declarar como un literal con corchetes [] y comas entre los elementos:
>>> no_elements = []
>>> no_elements
[]
>>> one_element = ["Guava"]
>>> one_element
['Guava']
>>> elements_separated_with_commas = ["Parrot", "Bird", 334782]
>>> elements_separated_with_commas
['Parrot', 'Bird', 334782]
Para mayor legibilidad, se pueden usar saltos de línea cuando hay muchos elementos o estructuras de datos anidadas dentro de una list:
>>> lots_of_entries = [
"Rose",
"Sunflower",
"Poppy",
"Pansy",
"Tulip",
"Fuchsia",
"Cyclamen",
"Lavender"
]
>>> lots_of_entries
['Rose', 'Sunflower', 'Poppy', 'Pansy', 'Tulip', 'Fuchsia', 'Cyclamen', 'Lavender']
# Each data structure is on its own line to help clarify what they are.
>>> nested_data_structures = [
{"fish": "gold", "monkey": "brown", "parrot": "grey"},
("fish", "mammal", "bird"),
['water', 'jungle', 'sky']
]
>>> nested_data_structures
[{'fish': 'gold', 'monkey': 'brown', 'parrot': 'grey'}, ('fish', 'mammal', 'bird'), ['water', 'jungle', 'sky']]
El constructor list() se puede usar vacío o con un iterable como argumento.
El constructor recorre los elementos del iterable y los agrega a la list en orden:
>>> no_elements = list()
>>> no_elements
[]
# The tuple is unpacked and each element is added.
>>> multiple_elements_from_tuple = list(("Parrot", "Bird", 334782))
>>> multiple_elements_from_tuple
['Parrot', 'Bird', 334782]
# The set is unpacked and each element is added.
>>> multiple_elements_from_set = list({2, 3, 5, 7, 11})
>>> multiple_elements_from_set
[2, 3, 5, 7, 11]
Los resultados de usar un constructor list con un string o un dict pueden ser sorprendentes:
# String elements (Unicode code points) are iterated through and added *individually*.
>>> multiple_elements_string = list("Timbuktu")
>>> multiple_elements_string
['T', 'i', 'm', 'b', 'u', 'k', 't', 'u']
# Unicode separators and positioning code points are also added *individually*.
>>> multiple_code_points_string = list('अभ्यास')
>>> multiple_code_points_string
['अ', 'भ', '्', 'य', 'ा', 'स']
# The iteration default for dictionaries is over the keys, so only key data is inserted into the list.
>>> source_data = {"fish": "gold", "monkey": "brown"}
>>> multiple_elements_dict_1 = list(source_data)
['fish', 'monkey']
Como el constructor list solo acepta iterables (o nada) como argumentos, los objetos que no son iterables lanzan un error de tipo.
Por lo tanto, es mucho más fácil crear una list de un solo elemento con el método literal.
# Numbers are not iterable, and so attempting to create a list with a number passed to the constructor fails.
>>> one_element = list(16)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
# Tuples *are* iterable, so passing a one-element tuple to the constructor does work, but it's awkward
>>> one_element_from_iterable = list((16,))
>>> one_element_from_iterable
[16]
Se puede acceder a los elementos dentro de las listas (así como a los elementos de otros tipos de secuencia, str y tuple) mediante un 0-based index y la notación de corchetes.
Los índices pueden ir de left --> right (empezando en cero) o de right --> left (empezando en -1).
| índice desde la izquierda ⟹ |
|
⟸ índice desde la derecha |
>>> breakfast_foods = ["Oatmeal", "Fruit Salad", "Eggs", "Toast"]
# Oatmeal is at index 0 or index -4.
>>> breakfast_foods[0]
'Oatmeal'
>>> breakfast_foods[-4]
'Oatmeal'
# Eggs are at index -2 or 2
>>> breakfast_foods[-2]
'Eggs'
>>> breakfast_foods[2]
'Eggs'
# Toast is at -1
>>> breakfast_foods[-1]
'Toast'
Se puede acceder a una sección de los elementos dentro de una list mediante la notación de slices (<list>[start:stop]).
Un slice se define como una secuencia de elementos en la posición index, tal que start <= index < stop.
El slicing devuelve una copia de los elementos «rebanados» y no modifica la list original.
También se puede usar un parámetro step [start:stop:step] para «saltar» o filtrar los elementos de la list (por ejemplo, un step de 2 selecciona elementos alternos en el rango):
>>> colors = ["Red", "Purple", "Green", "Yellow", "Orange", "Pink", "Blue", "Grey"]
# If there is no step parameter, the step is assumed to be 1.
>>> middle_colors = colors[2:6]
>>> middle_colors
['Green', 'Yellow', 'Orange', 'Pink']
# If the start or stop parameters are omitted, the slice will
# start at index zero, and will stop at the end of the list.
>>> primary_colors = colors[::3]
>>> primary_colors
['Red', 'Yellow', 'Blue']
El uso de la función integrada sum() en una lista devuelve la suma de todos los números de la lista:
>>> number_list = [1, 2, 3, 4]
>>> sum(number_list)
10
También puedes obtener la longitud de una lista con la función len():
>>> long_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
>>> len(long_list)
10
Las listas también se pueden combinar de varias formas:
# Using the plus + operator unpacks each list and creates a new list, but it is not efficient.
>>> new_via_concatenate = ["George", 5] + ["cat", "Tabby"]
>>> new_via_concatenate
['George', 5, 'cat', 'Tabby']
# Likewise, using the multiplication operator * is the equivalent of using + n times.
>>> first_group = ["cat", "dog", "elephant"]
>>> multiplied_group = first_group * 3
>>> multiplied_group
['cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant']
Las listas proporcionan un iterador y se pueden recorrer con un bucle de la misma forma que otros tipos de secuencia.
# Looping through the list and printing out each element.
>>> colors = ["Orange", "Green", "Grey", "Blue"]
>>> for item in colors:
... print(item)
...
Orange
Green
Grey
Blue
Para una explicación más detallada de los loops y los iterators, completa el concepto de loops.
Elyse está muy emocionada por jugar un poco de póker (y otros juegos de cartas) durante su próximo viaje a Vegas. Como es una gran fanática del «autoseguimiento», quiere armar unas funciones pequeñas que la ayuden con las tareas de seguimiento, y te pidió ayuda para pensarlas bien.
Elyse siente una especial predilección por el póker y quiere registrar cuántas rondas juega, y cuáles rondas son. Cada ronda tiene su propio número, y cada mesa muestra el número de la ronda que se está jugando en ese momento. Elyse elige una mesa y se sienta a jugar su primera ronda. Tiene pensado jugar tres rondas.
Implementa una función get_rounds(<round_number>) que reciba el número de la ronda actual y devuelva una sola list con esa ronda y las dos siguientes que vienen:
>>> get_rounds(27)
[27, 28, 29]
Elyse jugó algunas rondas en la primera mesa, luego se tomó un descanso y jugó algunas rondas más en una segunda mesa... ¡pero terminó con un array distinto por cada mesa! Quiere juntar los dos arrays para poder registrar todas las rondas de póker en el mismo lugar.
Implementa una función concatenate_rounds(<rounds_1>, <rounds_2>) que reciba dos arrays y devuelva una sola list formada por todas las rondas del primer list, seguidas de todas las rondas del segundo list:
>>> concatenate_rounds([27, 28, 29], [35, 36])
[27, 28, 29, 35, 36]
Hablando de algunas rondas anteriores de póker, otro jugador comenta lo parecido que se dieron dos de ellas. Elyse no está segura de si jugó esas rondas o no.
Implementa una función list_contains_round(<rounds>, <round_number>) que reciba dos argumentos: un array de rondas jugadas y un número de ronda. La función devolverá True si la ronda está en el array de rondas jugadas, y False si no:
>>> list_contains_round([27, 28, 29, 35, 36], 29)
True
>>> list_contains_round([27, 28, 29, 35, 36], 30)
False
Elyse quiere probar un juego nuevo llamado Black Joe. Es parecido al Black Jack, donde tu objetivo es que las cartas de tu mano sumen un valor objetivo, pero en Black Joe el objetivo es que el promedio de los valores de las cartas sea 7. El promedio se puede hallar sumando todos los valores de las cartas y luego dividiendo esa suma entre la cantidad de cartas de la mano.
Implementa una función card_average(<hand>) que devuelva el valor promedio de una mano de Black Joe.
>>> card_average([5, 6, 7])
6.0
En Black Joe, la velocidad es importante. Elyse va a intentar encontrar una manera más rápida de hallar el promedio.
Ha pensado en dos maneras de obtener un número parecido al promedio:
Implementa la función approx_average_is_average(<hand>), donde hand es un array que contiene los valores de las cartas de tu mano.
Devuelve True si una or ambas de las estrategias mencionadas arriba dan como resultado un número igual al promedio real.
Nota: todas las manos tienen una longitud impar, para que sea más fácil encontrar la mediana.
>>> approx_average_is_average([1, 2, 3])
True
>>> approx_average_is_average([2, 3, 4, 8, 8])
True
>>> approx_average_is_average([1, 2, 3, 5, 9])
False
Intrigada por los resultados de su experimento de promedios, Elyse se pregunta si tomar el promedio de las cartas en las posiciones pares frente al promedio de las cartas en las posiciones impares daría los mismos resultados. ¡Hora de otra función de prueba!
Implementa una función average_even_is_average_odd(<hand>) que devuelva un Boolean que indique si el promedio de las cartas en los índices pares es igual al promedio de las cartas en los índices impares.
>>> average_even_is_average_odd([1, 2, 3])
True
>>> average_even_is_average_odd([1, 2, 3, 4])
False
Cada undécima mano en Black Joe es una mano de bonificación con una regla extra: si la última carta que sacas es una Jack, duplicas su valor.
Implementa una función maybe_double_last(<hand>) que reciba una mano y verifique si la última carta es una Jack (11). Si la última carta es una Jack (11), duplica su valor antes de devolver la mano.
>>> hand = [5, 9, 11]
>>> maybe_double_last(hand)
[5, 9, 22]
>>> hand = [5, 9, 10]
>>> maybe_double_last(hand)
[5, 9, 10]
Regístrate en Exercism para aprender y dominar Python con 17 conceptos146 ejercicios y mentoría humana real, todo gratis.