Introducción a la programación en Python

clase 04a
Listas y strings (II)

Las listas y las cadenas de caracteres (strings) son dos tipos de objeto de los denominados secuencias.

Como tales, las listas y las cadenas de caracteres comparten varias funciones y métodos, aunque también tienen diferencias.

Las cadenas de caracteres son:

  • homogéneas: todos sus elementos son caracteres
  • inmutables: las cadenas no pueden cambiar sus elementos.

Las listas, por su parte, son:

  • heterogéneas: sus elementos pueden ser de diferentes tipos, incluidas otras listas.
  • mutables: se pueden modificar sus elementos, así como cambiar su longitud.
  • multidimensionales: las listas pueden anidarse (un elemento de una lista puede ser otra lista) hasta cualquier nivel arbitrario, pudiendo generar así estructuras de datos multidimensionales.

Indexado y particionado

En los iterables, se puede acceder a cualquiera de sus elementos mediante su índice, y a una porción, indicando un rango entre dos índices separado por dos puntos.

Por lo tanto, para las cadenas de caracteres son válidas las mismas operaciones de indexado y particionado vistas para las listas.

In [1]:
cadena = "En un lugar de la Mancha"
print(cadena)
En un lugar de la Mancha
In [2]:
cadena[0]
Out[2]:
'E'
In [3]:
cadena[-1]
Out[3]:
'a'
In [4]:
cadena[3:9]
Out[4]:
'un lug'
In [5]:
cadena[4::2]
Out[5]:
'nlgrd aMnh'
In [6]:
cadena[::-1]
Out[6]:
'ahcnaM al ed ragul nu nE'

Operaciones, funciones y métodos comunes a las secuencias

+ : concatenación

El operador + sirve para concatenar secuencias del mismo tipo, tanto cadenas como listas.

In [7]:
cadena = "foo" + "bar"
print(cadena)
foobar
In [8]:
lista = ['A', 1] + ['B', 2]
print(lista)
['A', 1, 'B', 2]

* : repetición

In [9]:
linea = '-' * 80
print(linea)
--------------------------------------------------------------------------------
In [10]:
lista_rep = ['A', 1] * 5
print(lista_rep)
['A', 1, 'A', 1, 'A', 1, 'A', 1, 'A', 1]

len()

Devuelve la longitud (cantidad de elementos) de una secuencia, tanto lista como cadena de caracteres.

In [11]:
lista_len = [1, 2, 3, 'A', 'B', 'C', [100, 'foo']]
cadena_len = "cadena de caracteres"
print(len(lista_len))
print(len(cadena_len))
7
20

min(), max()

Estas funciones devuelven el mínimo y el máximo respectivamente, de una secuencia.

En las cadenas pueden aplicarse sin limitaciones, y devuelven el carácter con menor o mayor índice Unicode.

In [12]:
cadena_m = "TheQuickBrownFoxJumpsOverTheLazyDog"
print(min(cadena_m))
print(max(cadena_m))
B
z

En el caso de las listas, min() y max() sólo pueden aplicarse si la lista es homogénea.

  • si sus elementos son números, devuelven el de mínimo y máximo valor
  • si son cadenas, devuelven el mínimo y el máximo de su ordenamiento alfabético.
In [13]:
lista_1 = [13, 23, 77, 9]
print(min(lista_1))
print(max(lista_1))
9
77
In [14]:
lista_2 = ['foo', 'bar', 'hola Python', 'zz']
print(min(lista_2))
print(max(lista_2))
bar
zz

Estas funciones no pueden operar sobre listas heterogéneas, que no son ordenables.

In [15]:
lista_3 = ['foo', 23, 11, 'bar']
print(max(lista_3))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-f016285f2344> in <module>
      1 lista_3 = ['foo', 23, 11, 'bar']
----> 2 print(max(lista_3))

TypeError: '>' not supported between instances of 'int' and 'str'

sum()

Esta función puede aplicarse solamente a listas homogéneas, y cuyos elementos sean todos de tipo numérico.

In [16]:
lista_4 = [1, 2, 3, 4]
print(sum(lista_4))
10

sorted()

La función sorted() devuelve una lista ordenada de los elementos de la secuencia que recibe como argumento (lista o cadena). La secuencia original no es modificada.

In [17]:
lista = [23, 13, 7, 37]
lista_ordenada = sorted(lista)
print(lista_ordenada)
print(lista)
[7, 13, 23, 37]
[23, 13, 7, 37]

La función sorted() siempre devuelve una lista, aunque reciba como argumento una cadena de caracteres.

In [18]:
cadena = "asdlk"
print(sorted(cadena))
['a', 'd', 'k', 'l', 's']

in

El operador in verifica si un elemento pertenece a una secuencia (lista o cadena), y devuelve la variable booleana True or False correspondiente.

In [19]:
"o" in "foo"
Out[19]:
True
In [20]:
"x" in "foo"
Out[20]:
False
In [21]:
lista_a = [12, 32, 14]
12 in lista_a
Out[21]:
True
In [22]:
13 in lista_a
Out[22]:
False

Como se vio en la clase 3, el operador in también se utiliza para recorrer secuencias u otros objetos iterables, en los ciclos generados por un for.

In [23]:
for i in lista_a:
    print(i)
12
32
14

not in

Es el contrario de in, devuelve verdadero cuando un elemento no está en una secuencia.

In [24]:
"o" not in "foo"
Out[24]:
False
In [25]:
"x" not in "foo"
Out[25]:
True

Operaciones para listas

Por ser secuencias mutables, las listas admiten operaciones que las modifican.

= asignación

Mediante el operador de asignación, se puede modificar el elemento correspondiente a un índice determinado.

In [26]:
mi_lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(mi_lista)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [27]:
mi_lista[0] = "A"
print(mi_lista)
['A', 1, 2, 3, 4, 5, 6, 7, 8, 9]

También se puede reemplazar una serie de elementos, especificando un rango de índices.

In [28]:
mi_lista[0:3] = "B"
print(mi_lista)
['B', 3, 4, 5, 6, 7, 8, 9]
In [29]:
mi_lista[0:1] = [0, 1, 2]
print(mi_lista)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [30]:
mi_lista[-1:] = ['A', 'B']
print(mi_lista)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 'A', 'B']

del

Con el operador del se pueden eliminar elementos o porciones de una lista, dando respectivamente su índice o un rango entre índices.

In [31]:
mi_lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(mi_lista)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [32]:
del(mi_lista[0])
print(mi_lista)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
In [33]:
del(mi_lista[7:])
print(mi_lista)
[1, 2, 3, 4, 5, 6, 7]
In [34]:
del(mi_lista[0:5:2])
print(mi_lista)
[2, 4, 6, 7]

Métodos de listas

Los métodos son funciones que se aplican a un determinado tipo de objeto. La sintaxis general es:

nombre_de_objeto.metodo()

.append()

El método append() agrega un elemento al final de una lista.

In [35]:
mi_lista = [0, 1, 2, 3, 4]
print(mi_lista)
[0, 1, 2, 3, 4]
In [36]:
mi_lista.append(5)
print(mi_lista)
[0, 1, 2, 3, 4, 5]

Con el método append() solo se puede agregar un único elemento.

In [37]:
mi_lista.append(6,7)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-625fce691e16> in <module>
----> 1 mi_lista.append(6,7)

TypeError: append() takes exactly one argument (2 given)

Se puede agregar un iterable, pero como un único elemento.

In [ ]:
mi_lista.append([6, 7])
print(mi_lista)

.extend()

La función extend() extiende una lista, agregando al final todos los elementos de un iterable.

In [38]:
mi_lista = [0, 1, 2]
print(mi_lista)
[0, 1, 2]
In [39]:
mi_lista.extend([3, 4, 5])
print(mi_lista)
[0, 1, 2, 3, 4, 5]
In [40]:
mi_lista.extend(range(6,9))
print(mi_lista)
[0, 1, 2, 3, 4, 5, 6, 7, 8]

.sort()

Ordena los elementos de una lista.

In [41]:
mi_lista = [4, 7, 5, 2, 11, 6]
print(mi_lista)
mi_lista.sort()
print(mi_lista) # la lista está ahora ordenada
[4, 7, 5, 2, 11, 6]
[2, 4, 5, 6, 7, 11]

La función sort() admite la opción reverse, que por defecto tiene el valor False.
De tener valor True, el ordenamiento se hace en sentido inverso.

In [42]:
otra_lista = [13, 5, 17, 9, 11, 6]
print(otra_lista)

otra_lista.sort(reverse=True)
print(otra_lista)
[13, 5, 17, 9, 11, 6]
[17, 13, 11, 9, 6, 5]

.reverse()

Invierte el orden de los elementos de una lista.

In [43]:
mi_lista = [4, 7, 5, 2, 11, 6]
print(mi_lista)

mi_lista.reverse()
print(mi_lista)
[4, 7, 5, 2, 11, 6]
[6, 11, 2, 5, 7, 4]

.count()

Esta función recibe un elemento como argumento, y cuenta la cantidad de veces que aparece en la lista.

In [44]:
lista = [3, 5, 11, 13, 5, 7, 3, 5]
print("11 -> ", lista.count(11))
print("5 -> ", lista.count(5))
print("9 -> ", lista.count(9))
9 in lista
11 ->  1
5 ->  3
9 ->  0
Out[44]:
False

.index()

Recibe un elemento como argumento, y devuelve el índice de su primera aparición en la lista.

In [45]:
lista = [3, 5, 11, 13, 5, 7, 3, 5]
print(lista.index(5))
1

La función admite como argumento adicional un índice inicial a partir de donde comenzar la búsqueda, opcionalmente también el índice final.

In [46]:
lista = [3, 5, 11, 13, 5, 7, 3, 5]
print(lista.index(5, 3))
4

La función devuelve un error si el elemento no se encuentra en la lista, o en el entorno definido.

In [47]:
lista = [3, 5, 11, 13, 5, 7, 3, 5]
print(lista.index(9))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-47-4c0151074ad8> in <module>
      1 lista = [3, 5, 11, 13, 5, 7, 3, 5]
----> 2 print(lista.index(9))

ValueError: 9 is not in list

.insert()

Por medio de la función .insert() se puede insertar un elemento en una lista. Se invoca de esta manera:

    *lista*.insert(*i, x*)

Inserta el elemento x en la lista, en el índice i.

In [48]:
lista = [3, 5, 11, 13, 5, 7, 3, 5]
lista.insert(2, "foo")
print(lista)
[3, 5, 'foo', 11, 13, 5, 7, 3, 5]

.remove()

Recibe como argumento un elemento, y borra su primera aparición en la lista.

In [49]:
lista = [3, 5, 11, 13, 5, 7, 3, 5]
lista.remove(5)
print(lista)
[3, 11, 13, 5, 7, 3, 5]

Devuelve un error si el elemento no se encuentra en la lista.

.pop()

Devuelve el último elemento de la lista, y lo borra de la misma.

In [50]:
lista = [3, 5, 11, 13, 5, 7, 3, 5]
print(lista.pop())
print(lista)
5
[3, 5, 11, 13, 5, 7, 3]

Opcionalmente puede recibir un argumento numérico, que funciona como índice del elemento (por defecto, -1)

In [51]:
lista = [3, 5, 11, 13, 5, 7, 3, 5]
print(lista.pop(2))
print(lista)
11
[3, 5, 13, 5, 7, 3, 5]

Definiendo una lista

Hay múltiples maneras de definir (crear) una lista:

  • por extensión, es decir, escribiendo entre corchetes cada uno de sus elementos por orden, separados por comas:
In [52]:
lista_extension = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(lista_extension)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  • mediante la función list() de un iterable. Por ejemplo, la lista anterior podría crearse mediante la función range(10):
In [53]:
lista_list = list(range(10))
print(lista_list)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Como argumento de la función list(), se puede usar cualquier objeto iterable, por ejemplo una cadena.

In [54]:
lista_list = list("Hola, Python")
print(lista_list)
['H', 'o', 'l', 'a', ',', ' ', 'P', 'y', 't', 'h', 'o', 'n']
  • creando una lista vacía, y agregando elementos iterativamente mediante el método .append, dentro de un bucle while o for:
In [55]:
lista_loop = []
for i in range(10):
    lista_loop.append(i)

print(lista_loop)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  • un principio similar al del método anterior puede expresarse de manera compacta en la propia asignación de la lista, mediante la operación llamada comprensión de lista (list comprehension).
In [56]:
lista_comprension = [x for x in range(10)]
print(lista_comprension)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

La forma general de la definición de una lista por comprensión es:

    [*expresión* for *ítem* in *iterable*]

Opcionalmente, se puede incluir un condicional en la expresión:

    [*expresión* for *ítem* in *iterable* if *condición*]
  • expresión puede ser cualquier expresión computable en Python, generalmente involucrando un ítem del iterable
  • iterable puede ser cualquier objeto iterable, como una secuencia (lista o cadena), la función range(), etc.

La salida siempre es una lista.

In [57]:
# crea una lista de números por extensión
numeros = [23, 7, 11, 41, 13, 38]
# eleva al cuadrado los números de la listas que sean menores que 20
# y crea una nueva lista
cuadrados = [x**2 for x in numeros if x < 20]
print(cuadrados)
[49, 121, 169]
In [58]:
cadena = "Hola Python"
lista = [x*2 for x in cadena if x != " "]
print(lista)
['HH', 'oo', 'll', 'aa', 'PP', 'yy', 'tt', 'hh', 'oo', 'nn']