Introducción a la programación en Python

clase 05a
Tipos I, tuples

Tipos en Python

Hay diversos tipos de objetos en Python, que a su vez se agrupan en diversas categorías:

categoría tipo descripción
None type(None) el objeto nulo None
Números int entero (precisión arbitraria)
float coma flotante
complex complejo
bool booleano (True o False)
Secuencias str cadena de caracteres
list lista
tuple tuple
range rango de enteros
Mapeo dict diccionario
Sets set set mutable
frozenset set inmutable

Como se vio en la clase 2, la función type() devuelve el tipo al que pertenece un objeto:

In [59]:
type(None)
Out[59]:
NoneType
In [60]:
type(3)
Out[60]:
int
In [61]:
type(3.2)
Out[61]:
float
In [62]:
type(True)
Out[62]:
bool
In [63]:
type("hola")
Out[63]:
str
In [64]:
type([2, 3, 5])
Out[64]:
list
In [65]:
type(range(10))
Out[65]:
range

Tuples

Al igual que las listas y las cadenas de caracteres (strings), los tuples son objetos de tipo secuencia.

Son muy similares a las listas y comparten varias de sus funciones y métodos, aunque su principal diferencia es que son inmutables.

Al igual que las listas, los tuples son:

  • secuencias ordenadas de elementos, que se acceden mediante un índice.
  • heterogéneos: sus elementos pueden ser de diferentes tipos, incluyendo listas u otros tuples.
  • multidimensionales: los tuples pueden anidarse hasta cualquier nivel arbitrario.

Pero por otra parte, los tuples son:

  • inmutables: al igual que las cadenas, los tuples no pueden modificarse.

Un tuple puede crearse simplemente mediante una secuencia de elementos separados por comas.
Opcionalmente pueden delimitarse los elementos mediante paréntesis (en vez de corchetes, como las listas).
En algunos casos, los paréntesis pueden ser necesarios para evitar ambigüedades. También podemos tomar como criterio siempre usar paréntesis para definir un tuple.

In [66]:
tuple1 = 1, 2, 3
tuple2 = (4, 5, 6)
print(tuple1, type(tuple1), sep='\t')
print(tuple2, type(tuple2), sep='\t')
(1, 2, 3)	<class 'tuple'>
(4, 5, 6)	<class 'tuple'>

Aternativamente, puede crearse un tuple mediante la función tuple(), con cualquier iterable como argumento:

In [67]:
tuple1 = tuple([1, 2, 3])
tuple2 = tuple(range(4, 7))
print(tuple1, type(tuple1), sep='\t')
print(tuple2, type(tuple2), sep='\t')
(1, 2, 3)	<class 'tuple'>
(4, 5, 6)	<class 'tuple'>

Un tuple vacío puede crearse con un par de paréntesis vacíos:

In [68]:
tuple1 = ()
print(tuple1, type(tuple1), sep='\t')
()	<class 'tuple'>

Para crear un tuple de un solo elemento es necesario poner una coma después del mismo, de lo contrario se evaluará la expresión.
Esto es independiente del uso de paréntesis.

In [69]:
no_tuple1 = 3*4
no_tuple2 = (3*4)
tuple1 = 3*4,
tuple2 = (3*4,)
print(no_tuple1, type(no_tuple1), sep='\t')
print(no_tuple2, type(no_tuple2), sep='\t')
print(tuple1, type(tuple1), sep='\t')
print(tuple2, type(tuple2), sep='\t')
12	<class 'int'>
12	<class 'int'>
(12,)	<class 'tuple'>
(12,)	<class 'tuple'>

Funciones y métodos de tuples

Los tuples disponen de todas las funciones y los métodos comunes a las secuencias inmutables, vistas anteriormente.

T1 + T2concatenación
T * N, N * Trepetición
X in T
X not in T
pruebas de pertenencia
T[i]acceso por indexado
T[i:j], T[i:j:k]acceso por particionado, con incremento opcional
len(T)longitud
min(T), max(T)ítem mínimo y máximo
for item in T:
[expr for item in T]
iteración

También admite dos métodos específicos:

.index()
.count()

Estos métodos funcionan de la misma manera que en las listas, tal como fue visto en la clase pasada.

Ejemplos

Se puede repetir la información almacenada en un tuple:

In [70]:
tuple1 = (1, 2)
print(tuple1)
tuple1 *= 3
print(tuple1)
(1, 2)
(1, 2, 1, 2, 1, 2)

Es posible concatenar dos tuples, conformando un nuevo tuple:

In [71]:
tuple1 = (1, 2)
tuple1 *= 3
tuple2 = (3, 4, 5, 6)
mi_tuple = tuple1 + tuple2
print(mi_tuple)
(1, 2, 1, 2, 1, 2, 3, 4, 5, 6)

También se puede acceder a uno o varios elementos por indexado:

In [72]:
tuple1 = (1, 2)
tuple1 *= 3
tuple2 = (3, 4, 5, 6)
mi_tuple = tuple1 + tuple2
print(mi_tuple)
print(mi_tuple[2])
print(mi_tuple[3:6])
(1, 2, 1, 2, 1, 2, 3, 4, 5, 6)
1
(2, 1, 2)

Es posible verificar la pertenencia de un determinado dato en un tuple, buscar el valor máximo y mínimo, y también preguntar por su largo total:

In [73]:
tuple1 = (1, 2)
tuple1 *= 3
tuple2 = (3, 4, 5, 6)
mi_tuple = tuple1 + tuple2
print(mi_tuple)
print(9 in mi_tuple)
print(6 in mi_tuple)
print(max(mi_tuple), min(mi_tuple))
print(len(mi_tuple))
(1, 2, 1, 2, 1, 2, 3, 4, 5, 6)
False
True
6 1
10

Los tuples pueden recorrerse, por ejemplo al definir una lista de comprensión:

In [74]:
tuple1 = (1, 2)
tuple1 *= 3
tuple2 = (3, 4, 5, 6)
mi_tuple = tuple1 + tuple2
print(mi_tuple)
print([x**3 for x in mi_tuple])
(1, 2, 1, 2, 1, 2, 3, 4, 5, 6)
[1, 8, 1, 8, 1, 8, 27, 64, 125, 216]

Es posible averiguar en qué índice se encuentra determinado elemento, así como contar cuántas veces aparece dentro del tuple:

In [75]:
tuple1 = (1, 2)
tuple1 *= 3
tuple2 = (3, 4, 5, 6)
mi_tuple = tuple1 + tuple2
print(mi_tuple)
print(mi_tuple.index(4))
print(mi_tuple.count(2))
(1, 2, 1, 2, 1, 2, 3, 4, 5, 6)
7
3

Zip

La función zip permite recorrer más de un iterable en paralelo, y devuelve una secuencia de tuples donde cada elemento pertence a cada uno de los iterables.

In [76]:
lista1 = [1, 2, 3, 4]
lista2 = ['a', 'b', 'c', 'd']

# crea una lista por comprensión
lista_zip1 = [(x, y) for x, y in zip(lista1, lista2)]
print(lista_zip1)

# crea una lista mediante la función list()
lista_zip2 = list(zip(lista1, lista2))
print(lista_zip2)
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]

La función zip puede utilizarse en todo tipo de estructuras en las que se recorren iterables.
Los iterables pueden ser de cualquier tipo (listas, tuples, cadenas de caracteres, función range(), etc.).

In [77]:
lista = list(zip('hola', range(1,5)))
print(lista)
[('h', 1), ('o', 2), ('l', 3), ('a', 4)]
In [78]:
for (x, y) in zip('hola', range(1,5)):
    print(x*y)
h
oo
lll
aaaa

Si los iterables no tienen la misma longitud, la función zip() ajusta la iteración a la longitud del más corto, e ignora los demás.

In [79]:
lista = list(zip([1, 2, 3, 4, 5, 6], "foo"))
print(lista)
[(1, 'f'), (2, 'o'), (3, 'o')]

Ejemplo 5.1

Dada una lista de alturas en nota MIDI, y una lista de duraciones en fracciones de tiempo, generar una lista de notas en forma de tuples (altura, duración). Imprimir en columnas.

In [80]:
# listas con las alturas y las duraciones
alturas = [72, 62, 59, 56, 67, 70, 66, 57, 63, 76, 73, 65]
duraciones = [1.5, 1.75, 0.25, 1, 1.5, 1, 0.5, 0.5, 0.75, 0.75, 0.75, 0.75]

# lista con las notas en forma de tuples
notas = list(zip(alturas, duraciones))

# imprimir la lista, y en columnas
print(notas)
for i in notas:
    print(i[0], i[1], sep='\t') 
[(72, 1.5), (62, 1.75), (59, 0.25), (56, 1), (67, 1.5), (70, 1), (66, 0.5), (57, 0.5), (63, 0.75), (76, 0.75), (73, 0.75), (65, 0.75)]
72	1.5
62	1.75
59	0.25
56	1
67	1.5
70	1
66	0.5
57	0.5
63	0.75
76	0.75
73	0.75
65	0.75