Tipos de Datos en Python: Tuplas

El tipo de dato tuple representa lo que podría ser una de las estructuras de datos más simple de Python, son secuencias inmutables de objetos arbitrarios y heterogéneos. Se emplean generalmente para denotar que su contenido no debe ser modificado. Constituyen un tipo de dato muy empleado en Python, fundamentalmente en la definición y llamada de funciones y en otras situaciones donde sea necesario emplear la capacidad de las tuplas para ser empaquetadas y desempaquetadas.

Los beneficios de la inmutabilidad son la simplicidad, la reducida demanda de espacio de almacenamiento y el alto desempeño en su procesamiento, cuestiones en las que superan con creces a la listas (list). Por otra parte, esta característica de las tuplas (inmutabilidad), nos permite emplearlas como claves en diccionarios (dict) y como elementos en los conjuntos (set).

Algunos ejemplos de literales válidos del tipo tuple en Python son:

()

(1,)

1, 2, 3

(1, 2, 3)

(1, 'Two', [4, 5], 6.0)

('Welcome', 'to', 'Python', 'Scouts')

(('Tuple', 'inside'), {'and': 'a dictionary too'})

El tipo tuple se define como una clase de la forma:

class tuple([iterable]):

El constructor de esta clase devuelve una tupla cuyos elementos quedan ordenados en la misma forma que lo estaban los elementos de iterable. Este iterabel puede ser una secuencia, un contenedor que soporte iteración o un iterador.

Las tuplas pueden definirse de varias maneras:

  • usando un par de paréntesis creamos una tupla vacía: ()

  • usando una coma final, creamos una tupla de un solo elemento o singleton: 1, ó (1,)

  • usando coma para separar los elementos: 1, 2, 3 ó (1, 2, 3)

Notemos que es la coma la que define la tupla y no los paréntesis. Los paréntesis son opcionales, excepto cuando creamos tuplas vacías a partir del uso de paréntesis o cuando pasamos una tupla como argumento en una llamada de función. De forma general es recomendable emplear los paréntesis, pues ellos mejoran significativamente la legibilidad del código.

Si empleamos la clase tuple() para crear tuplas, podemos proceder de la forma siguiente:

>>> t = tuple() # Tupla vacía

>>> type(t)

<class 'tuple'>

>>> t

()

>>> t1 = tuple([1, 2, 3]) # Creamos la tupla a partir de una lista

>>> type(t1)

<class 'tuple'>

>>> t1

(1, 2, 3)

>>> t2 = tuple('abc') # Finalmente creamos la tupla a partir de una cadena

>>> type(t2)

<class 'tuple'>

>>> t2

('a', 'b', 'c')

Índices y rebanado (slicing)

Como ya hemos visto, las tuplas son secuencias inmutables de datos con tipos heterogéneo. Las secuencias por su parte, son colecciones de datos ordenados, cuyos elementos reciben una numeración única de izquierda a derecha que comienza en cero y termina en la cantidad de elementos de la secuencia, menos uno; es decir, si tenemos una tupla de 10 elementos, la numeración de los mismos comienza en 0, y termina en 9 (10 – 1).

La posición relativa o índice de cada elemento dentro de la secuencia, está definida por su numeración, de esta forma si tenemos una tupla t = ('a', 'b', 'c'), su elemento 0 será 'a', el 1 será 'b' y el 3 será 'c'.

Es posible además, enumerar las posiciones de los elementos dentro de la secuencia de derecha a izquierda, esta vez empleando índices negativos y comenzando por -1, que representa el último elemento de la secuencia. Así, si tomamos el elemento -1 de nuestra tupla t, obtendremos a 'c', el -2 sería 'b' y el -3, 'a'.

Para acceder a los elementos dentro de la secuencias se emplea el operador [i], donde i representa el índice numerico del elemento que deseamos extraer. Veamos algunos ejemplos:

>>> t = ('a', 'b', 'c')

>>> t

('a', 'b', 'c')

>>> t[0] # Primer elemento de t

'a'

>>> t[1] # Segundo elemento de t

'b'

>>> t[-1] # Último elemento de t

'c'

>>> t[-3]

'a'

Otra de las opciones que tenemos a la hora de manipular secuencia, es el rebanado o slicing, este consiste en extraer un fragmento de una secuencia en función de nuestras necesidades. Por ejemplo, supongamos que tenemos una tupla que almacena diez valores y necesitamos extraer los últimos cinco valores, en este caso podemos emplear el rebanado, para lo cual nos servirá el operador [start:end], es decir, un juego de corchetes con un intervalo definido en su interior a partir del empleo de los dos puntos “:” como separador. En este caso, start es el índice del primer elemento del intervalo y end será el índice de cierre del intervalo. Debemos hacer notar que Python emplea lo que podemos llamar intervalos semi-abiertos, es decir, el elemento con índice igual a end no estará incluido en el intervalo extraído, por tanto, nuestra rebanada incluirá solo los elementos k donde start <= k < end. Si uno de los índices (start o end) es omitido, Python asume start como el primer elemento de la secuencia y end como el último (que en este caso queda incluido en la rebanada extraída). Si ambos índices son omitidos, obtendremos una copia de la secuencia que estemos manipulando. Veamos cómo funciona esto en la práctica.

>>> t = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

>>> t

(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

>>> t[6:-1] # Extraemos desde el séptimo elemento hasta el último (no incluido)

(7, 8, 9)

>>> t[5:] # Del sexto hasta el último (incluido)

(6, 7, 8, 9, 10)

>>> t[:] # Hacemos una copia de la tupla

(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

>>> t[:5] # Desde el primero hasta el sexto elemento (no incluido)

(1, 2, 3, 4, 5)

>>> t[3:5] # Del cuarto a sexto (no incluido)

(4, 5)

>>> t[3:]

(4, 5, 6, 7, 8, 9, 10)

Es posible agregar un tercer ingrediente al rebanado, es decir, podemos emplear el operador de rebanado (slicing) de la forma [start:end:step]. El factor step representa el salto o avance, es decir, la cantidad de índices que vamos a avanzar en la secuencia.

>>> t = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

>>> t[3:6:2]

(4, 6)

>>> t[::2]

(1, 3, 5, 7, 9)

>>> t[1::2]

(2, 4, 6, 8, 10)

Desempaquetado de tuplas (tuple unpacking)

La asignación de tuplas es un proceso mediante el cual, a una tupla de identificadores se le asigna una tupla de valores según su posición. En este caso, Python se encarga de asignar los elementos de la tupla del lado derecho de la expresión a los identificadores del lado izquierdo, por posición.

>>> yum = ('yum', 'YUM') # tupla inicial

>>> spam, ham = yum

>>> spam

'yum'

>>> ham

'YUM'

También es posible la asignación de tuplas donde a una tupla de identificadores se le asigna una tupla de valores directamente, es decir:

>>> spam, ham = 'yum', 'YUM'

>>> spam

'yum'

>>> ham

'YUM'

Esta característica de Python viene a mano cuando necesitamos intercambiar los valores asignados a dos identificadores, pues nos permite prescindir del empleo de una variable auxiliar o temporal y realizar la operación en un solo paso:

>>> x = 1

>>> y = 100

>>> x, y = y, x # Intercambiamos valores

>>> x

100

>>> y

1

En otros lenguaje para realizar esta operación tendríamos que hacer:

x = 1

y = 100

tmp = y # Conservamos el valor de y en una variable temporal

y = x

x = tmp

Por otra parte, en Python 3.x, también podemos hacer uso de desempaquetado extendido mediante el operador *, veamos un ejemplo:

>>> t = (1, 2, 3, 4, 5)

>>> a, *b = t

>>> a

1

>>> b

[2, 3, 4, 5]

Como podemos apreciar, se le asigna el primer elemento de t al identificador a por posición, y el resto de los elementos de t, se empaquetan en b.

>>> x, *y, z = t

>>> x

1

>>> y

[2, 3, 4]

>>> z

5

En el ejemplo anterior, se le asigna a x el primer elemento de t, los elementos intermedios se empaquetan en y, y finalmente z recibe el valor del último elemento de t por posición.

En las versiones más recientes de Python, se ha generalizado el empaquetado y desempaquetado de secuencias (no solo de tuplas), por tanto es válido escribir algo como:

>>> [spam, ham] = ['yum', 'YUM']

>>> spam

'yum'

>>> ham

'YUM'

O como:

>>> a, *b = 'spam'

>>> a

's'

>>> b

['p', 'a', 'm']

La asignación de tuplas es una herramienta tan versátil que puede ser empleada con naturalidad en los ciclos for, por ejemplo:

>>> T = [(1, 2), (3, 4), (5, 6)]

>>> for a, b in T:

... print(a, b)

...

1 2

3 4

5 6

Legibilidad con collections.namedtuple

Uno de los elementos más recurrentes en la filosofía de Python es la legibilidad del código. No en vano uno de los principios definidos en el Zen de Python reza: “Readability counts”. En este sentido el módulo collections (de la librería estándar) incluye una clase llamada namedtuple que tiene como primer objetivo el de clarificar el código que escribimos. Supongamos que tenemos el siguiente código:

file: color0.py

p = (170, 0.1, 0.6)

if p[1] >= 0.5:

    print('Eso es brillante')

if p[2] >= 0.5:

    print('Eso es claro')

La pregunta salta a la vista: ¿Qué representa p?

Ahora modificamos un poco el código par usar una namedtuple.

file: color1.py

from collections import namedtuple

Color = namedtuple('Color', ['hue', 'saturation', 'luminosity'])

p = Color(170, 0.1, 0.6)

if p.saturation >= 0.5:

    print('Eso es brillante')

if p.luminosity >= 0.5:

    print('Eso es claro')

Saque usted, sus propias conclusiones…

Lecturas Recomendadas

Para profundizar en el estudio y conocimiento del tipo de datos tuple recomendamos la lectura de la documentación oficial de Python en su acápite 4.6.5. Tuples. Recomedamos además la lectura del Capítulo 4 “Introducing Python Object Types”, acápite “Tuples” del libro “Learnig Python”5ta Edición, por Mark Lutz, publicado por la Editorial O’Reilly.

Bien, esto es todo por ahora, si este artículo te resultó interesante y/o útil, compártelo para que otros también puedan acceder a él. Déjanos tus comentarios y podremos mejorar nuestros contenidos.

Gracias de antemano,

lpozo

4 comentarios

Ir al formulario de comentarios

    • ronny en 8 mayo, 2018 a las 12:16 am

    hola necesito saber si saben de alguien que haya desarrollado scripts en Phyton para Autodesk Maya??

    1. Yo realmente no he hecho esto que pides, esperemos que algún lector sí lo haya hecho y te pueda responder por acá.
      saludos,
      lpozo

    • FATOMIX en 15 mayo, 2018 a las 3:16 am

    Hola leodanis, saludos y felicidades primeramente por mantener este blog que esta bueno. Mira tengo 2 dudas que quisieras que me aclararas !!! #1 Al actualiza mi sistema linux desde internet al ejecutar python y buscar la ayuda: help(modules) me salta un error y no me muestra los modulos sabes como arreglarlo ??? y #2 —-> Crees que pudieras subir varios libros de python bacanes ??? yo tengo 1 gb de libros pero a lo mejor me faltan algunos, podemos compartir.
    CORREO: myoandro@nauta.cu
    PAGINA: securewhomix.cubava.cu

    1. En primer lugar agradecer tus palabras de elogio hacia el Blog. Respecto a tu duda # 1, creo que debes estar haciendo algo mal, es decir, prueba esto y dime si te funciona
      >>> import sys
      >>> help(sys)
      con esto debe salirte la documentación del módulo sys, este mismo proceder debes emplear con cualquier otro módulo.
      La # 2 es más compleja, es muy limitado el espacio que disponemos en Refejos para el contenido del Blog, por eso y además por temas legales, no publicamos libros en el Blog, solo nos limitamos a recomendar algunos de ellos en dependencia del tema tratado.
      Te puedo recomendar que te llegues al sitio: http://www.allitebooks.com/ y hagas una búsqueda para Python, ahí deben salirte muchos libros que a lo mejor no tienes en tu colección. Podemos intercambiar algunos por correo, todo depende de tus intereses y de lo que yo tenga.
      saludos y gracias nuevamente,
      lpozo
      PD: Disculpa la demora en responde a tu comentario, he estado un poco off-line en los últimos días y no había tenido chance de revisar.

Los comentarios han sido desactivados.