Next Up Previous Hi Index

Chapter 8

\documentclass[oneside,spanish]{book \usepackage[T1]{fontenc} \usepackage[latin1]{inputenc} \usepackage{babel} \setcounter{secnumdepth}{3} \setcounter{tocdepth}{3} \usepackage{graphics} \makeatletter %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands. \providecommand{\LyX}{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} \addto\extrasspanish{\bbl@deactivate{~}} \makeatother \begin{document} \chapter{Listas} \index{listas} \index{elementos} \index{sequencias} Una \textbf{lista} es un conjunto ordenado de valores, en el cual cada valor va identificado por un índice. Los valores que constituyen una lista se llaman sus \textbf{elementos}. Las listas son similares a las cadenas de texto (\emph{strings}), que son conjuntos ordenados de caracteres, excepto en que los elementos de una lista pueden ser de cualquier tipo. Llamamos \textbf{secuencias} a las listas y cadenas (o ristras), y a cualquier otra cosa que se comporte como un conjunto ordenado. Hay varias operaciones que podemos aplicar a cualquier tipo de secuencia. \section{Valores de una lista} Hay varias maneras de crear una nueva lista; la más sencilla es encerrar sus elementos entre corchetes: \begin{verbatim} [10, 20, 30, 40] ["spam", "elástico", "tragar"] \end{verbatim} El primer ejemplo es una lista de cuatro enteros. El segundo es una lista de tres cadenas de texto. Los elementos de una lista no tienen por qué ser del mismo tipo. La siguiente lista contiene una cadena, un número con decimales y un entero, y el último elemento es otra lista, \texttt{{[}10, 20{]}}. \begin{verbatim} ["hola", 2.0, 5, [10, 20]] \end{verbatim} Se dice que una lista dentro de otra lista está \textbf{anidada}.\index{listas!anidadas} Las listas que contienen números enteros consecutivos son comunes, de manera que Python proporciona una manera sencilla de crearlas: \begin{verbatim} >>> range(1,5) [1, 2, 3, 4] \end{verbatim} La función \texttt{range} toma dos argumentos y devuelve una lista que contiene todos los enteros entre el primero y el segundo, ¡incluyendo el primero pero no el segundo! Hay dos formas alternativas para \texttt{range}. Con un solo argumento, crea una lista que empieza desde 0: \begin{verbatim} >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] \end{verbatim} Si hay un tercer argumento, especificará el espacio entre dos valores sucesivos; a esto algunas veces se le llama \emph{paso} (\emph{step}). Este ejemplo cuenta de 1 a 10 de dos en dos (con pasos de 2). \begin{verbatim} >>> range(1, 10, 2) [1, 3, 5, 7, 9] \end{verbatim} Para terminar, hay una lista especial que no contiene elementos. Se la llama lista vacía y se representa \texttt{{[}{]}}. Con todas estas maneras para crear listas, sería defraudante que no pudiéramos asignar valores de listas a variables o pasar listas como parámetros a funciones. Por supuesto que podemos. \begin{verbatim} vocabulario = ["mejorar", "castigar", "defenestrar"] numeros = [17, 123] vacio = [] print vocabulario, numeros, vacio ['mejorar', 'castigar', 'defenestrar'] [17, 123] [] \end{verbatim} \section{Acceso a los elementos} \index{listas!elementos} La sintaxis para acceder a los elementos de una lista es la misma que para acceder a los caracteres de una cadena: El operador corchetes \texttt{{[}{]}}. La expresión dentro de los corchetes especifica el índice. Recuerde que los índices siempre comienzan en cero. \begin{verbatim} print numeros[0] numeros[1] = 5 \end{verbatim} El operador \texttt{{[}{]}} puede aparecer en cualquier parte de una expresión. Cuando aparece a la izquierda de una asignación, cambia uno de los elementos de la lista, de manera que el primer elemento de \texttt{numeros}, que era 123, ahora es 5. Se puede usar como índice cualquier expresión de tipo \texttt{int}. \begin{verbatim} >>> numeros[3-2] 5 >>> numeros[1.0] TypeError: sequence index must be integer \end{verbatim} Si intenta acceder (leer o modificar) un elemento que no existe, obtendrá un \texttt{IndexError}. \begin{verbatim} >>> numeros[2] = 5 IndexError: list assignment index out of range \end{verbatim} Como los índices empiezan en cero, no hay elemento con índice 2. Si se da un índice negativo, se cuenta hacia atrás desde el final de la lista. \begin{verbatim} >>> numeros[-1] 5 >>> numeros[-2] 17 >>> numeros[-3] IndexError: list index out of range \end{verbatim} \texttt{numeros{[}-1{]}} es el último elemento de la lista, \texttt{numeros{[}-2{]}} es el penúltimo, y \texttt{numeros{[}-3{]}} no existe. Una de las manera más comunes de indizar una matriz es una variable de bucle. Por ejemplo: \begin{verbatim} jinetes = ["guerra", "hambre", "peste", "muerte"] i = 0 while i < 4: print jinetes[i] i = i + 1 \end{verbatim} Este bucle \texttt{while} cuenta desde 0 hasta 4, la condición falla y acaba el bucle. Por tanto, el cuerpo del bucle sólo se ejecuta cuando \texttt{i} es 0, 1, 2 y 3. Cada vez que usamos la variable \texttt{i} dentro del bucle como índice de la lista, se imprime el elemento \texttt{i}-ésimo. Este tipo de \textbf{recorrido de lista} es muy común. \index{listas!recorrido} \section{Longitud (tamaño) de una lista} \index{listas!longitud} La función \texttt{len} toma una lista y devuelve su tamaño. Es una buena idea usar este valor como límite superior de un bucle, en lugar de una constante. De esta manera, si el tamaño de la lista cambia, no habrá que estar haciendo cambios en todos los bucles; funcionarán correctamente con cualquier tamaño de lista. \begin{verbatim} jinetes = ["guerra", "hambre", "peste", "muerte"] i = 0 while i < len(jinetes): print jinetes[i] i = i + 1 \end{verbatim} La última vez que se ejecuta el cuerpo del bucle, \texttt{i} es \texttt{len(jinetes) - 1}, que es el índice del último elemento. Cuando \texttt{i} se iguala a \texttt{len(jinetes)}, la condición falla y no se ejecuta el cuerpo, lo que es una cosa buena, ya que si no habría un error. Aunque una lista puede contener otra lista como elemento, la lista anidada cuenta como un elemento sencillo. El tamaño de esta lista \begin{verbatim} ['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]] \end{verbatim} es 4. \section{Listas y bucles \texttt{for}} Usar un bucle para recorrer los elementos de una lista es algo tan común que Python proporciona una operación especial para ello, el bucle \texttt{for}. \begin{verbatim} for VARIABLE in LISTA: CUERPO \end{verbatim} Esta sentencia es equivalente a \begin{verbatim} i = 0 while i < len(LISTA): VARIABLE = LISTA[i] CUERPO i = i + 1 \end{verbatim} Excepto en que no es necesario usar la variable de bucle. Usando esta sintaxis, el bucle anterior es mucho más sencillo: \begin{verbatim} for jinete in jinetes: print jinete \end{verbatim} Más aún, casi se lee igual que en español, {}``Para (cada) jinete en (la lista de) jinetes, imprime (el nombre del) jinete.'' Se puede usar cualquier expresión de lista en un bucle \texttt{for}. \begin{verbatim} for fruta in ["plátano", "manzana", "membrillo"]: print "¡Me gusta comer " + fruta + "s!" for numero in range(20): if numero % 2 == 0: print numero \end{verbatim} El primer ejemplo se come todas las frutas de la lista. El segundo ejemplo imprime todos los números pares entre el 0 y el 19. \section{Operaciones con listas} \index{operaciones con listas} \index{listas!operaciones con} \index{operadores!para listas} \index{operaciones!con listas} Las listas disponen de varias operaciones más. El operador \texttt{+} las concatena: \begin{verbatim} >>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = a + b >>> print c [1, 2, 3, 4, 5, 6] \end{verbatim} De forma similar, el operador \texttt{{*}} repite una lista un número dado de veces: \begin{verbatim} >>> [0] * 4 [0, 0, 0, 0] >>> [1, 2, 3] * 3 [1, 2, 3, 1, 2, 3, 1, 2, 3] \end{verbatim} En el primer ejemplo la lista \texttt{{[}0{]}} contiene un solo elemento que es repetido cuatro veces. En el segundo ejemplo, la lista \texttt{{[}1, 2, 3{]}} se repite tres veces. La sentencia \texttt{del} elimina un elemento de una lista. \begin{verbatim} >>> a = ['uno', dos', 'tres'] >>> del a[1] >>> a ['uno', 'tres'] \end{verbatim} \section{Porciones (slices)} \index{porciones} \index{listas!porciones} Todas las operaciones sobre porciones que se aplican a las cadenas de texto funcionan con las listas también. \begin{verbatim} >>> lista = ['a', 'b', 'c', 'd', 'e'] >>> lista[1:3] ['b', 'c'] >>> lista[:4] ['a', 'b', 'c', 'd'] >>> lista[3:] ['d', 'e'] >>> lista[:] ['a', 'b', 'c', 'd', 'e'] \end{verbatim} Además, las operaciones de porciones en las listas pueden aparecer a la izquierda de una sentencia de asignación. Esto no es así con las cadenas, ya que son inmutables. El siguiente ejemplo reemplaza varios elementos en una lista. \begin{verbatim} >>> lista = ['a', 'b', 'c', 'd', 'e'] >>> lista[1:3] = ['x', 'y'] >>> print lista ['a', 'x', 'y', 'd', 'e'] \end{verbatim} Además, puede eliminar varios elementos de una lista asignándoles la lista vacía. \begin{verbatim} >>> lista = ['a', 'x', 'y', 'd', 'e'] >>> lista[1:3] = [] >>> lista ['a', 'd', 'e'] \end{verbatim} Y puede añadir elementos a la lista comprimiéndolos en una porción de sólo un elemento. \begin{verbatim} >>> lista = ['a', 'd', 'e'] >>> lista[1:1] = ['b', 'c'] >>> lista ['a', 'b', 'c', 'd', 'e'] \end{verbatim} ...y \texttt{lista} está igual que cuando empezó. \section{Objetos y valores} Considere las siguientes asignaciones: \begin{verbatim} a = "plátano" b = a \end{verbatim} Está claro que \texttt{a} y \texttt{b} tienen ambos el mismo valor, la cadena \texttt{\char`\"{}banana\char`\"{}}. Pero hay dos posibles estados finales: \vspace{0.1in} \centerline{\includegraphics{list1.eps} } \vspace{0.1in} En un caso, \texttt{a} y \texttt{b} se refieren a dos {}``cosas'' diferentes que tienen el mismo valor. En el segundo caso, se refieren a la misma {}``cosa''. Estas {}``cosas'' tienen nombres; se les denomina \textbf{objetos}. Un objeto es una cosa a la que uno se puede referir. Se puede preguntar cual de estas dos cosas hace Python. ¿Existe algún experimento que pueda realizar para comprobarlo? \begin{verbatim} >>> id(a) 135044008 >>> id(b) 135044008 \end{verbatim} Cada objeto tiene un identificador único; la función \texttt{id} devuelve el identificador de un objeto dado. En este caso, obtenemos el mismo identificador dos veces, lo que indica que \texttt{a} y \texttt{b} se refieren al mismo objeto. Como las cadenas de texto son inmutables, no hay diferencia práctica entre los dos posibles estados. Para tipos mutables como las listas, sí que importa. Cuando crea dos listas, obtiene dos objetos: \begin{verbatim} >>> a = [1, 2, 3] >>> b = [1, 2, 3] >>> id(a) 135045528 >>> id(b) 135041704 \end{verbatim} De manera que el diagrama de estado sería tal como éste: \vspace{0.1in} \centerline{\includegraphics{list2.eps} } \vspace{0.1in} \texttt{a} y \texttt{b} tienen el mismo valor, pero no se refieren al mismo objeto. \section{Alias (poner sobrenombres)} \index{alias} \index{referencias a objetos!alias} Las variables contienen referencias a los objetos. Si asigna una variable a otra, significa que ambas variables se refieren al mismo objeto. \begin{verbatim} >>> a = [1, 2, 3] >>> b = a \end{verbatim} En este caso, el diagrama de estados sería como éste: \vspace{0.1in} \centerline{\includegraphics{list3.eps} } \vspace{0.1in} Como la misma lista tiene dos nombres diferentes, \texttt{a} y \texttt{b}, podemos decir que se le ha puesto un \textbf{alias} (sobrenombre). Los cambios que se hace a un alias, se pueden ver en el otro. \begin{verbatim} >>> b[0] = 5 >>> print a [5, 2, 3] \end{verbatim} Aunque este comportamiento puede ser útil, a veces es inesperado o indeseable. Por ejemplo, si queremos modificar una lista y mantener una copia del original, necesitaremos ser capaces de hacer una copia de la lista en sí, no sólo de su referencia. Este proceso a veces se denomina clonado, para evitar la ambigüedad de la palabra {}``copia''. \section{Clonar listas} \index{listas!clonado} No hay ninguna orden interna a Python para clonar listas, pero podemos obtener el mismo efecto usando porciones. \begin{verbatim} >>> a = [1, 2, 3] >>> b = [] >>> b[:] = a[:] >>> print b [1, 2, 3] \end{verbatim} Comenzamos inicializando \texttt{b} al valor de la lista vacía. En ese momento tomamos una porción de \texttt{a} que contiene el total de la lista, y lo usamos para reemplazar una porción de \texttt{b}. \begin{quote} \emph{Como ejercicio, dibuje un diagrama de estado del resultado.} \end{quote} Ahora tenemos libertad de hacer cambios en \texttt{b} sin preocuparnos de \texttt{a}: \begin{verbatim} >>> b[0] = 5 >>> print a [1, 2, 3] \end{verbatim} \section{List como parámeteros} \index{listas!como parámetros} \index{funciones!parámetros} \index{parámetros!listas} Cuando se pasa una lista como argumento, en realidad se pasa una referencia a ella. Por ejemplo, la función \texttt{cabeza} toma una lista como parámetro y devuelve el primer elemento. \begin{verbatim} def cabeza(lista): return lista[0] \end{verbatim} Así es como se usa. \begin{verbatim} >>> numeros = [1,2,3] >>> cabeza(numeros) 1 \end{verbatim} En este caso, el parámetro \texttt{lista} es un alias de la variable \texttt{numeros}. Si la función modifica una lista pasada como parámetro, el que hizo la llamada verá el cambio. \texttt{borra\_cabeza} elimina el primer elemento de una lista. \begin{verbatim} def borra_cabeza(lista): del lista[0] \end{verbatim} Aquí vemos el uso de \texttt{borra\_cabeza}: \begin{verbatim} >>> numeros = [1,2,3] >>> borra_cabeza(numeros) >>> print numeros [2, 3] \end{verbatim} Si una función devuelve una lista, en realidad devuelve una referencia a la lista. \texttt{cola} devuelve una lista que contiene todos los elementos de una lista dada, excepto el primero. \begin{verbatim} def cola(lista): return lista[1:] \end{verbatim} Aquí vemos cómo se usa \texttt{cola}: \begin{verbatim} >>> numeros = [1,2,3] >>> resto = cola(numeros) >>> print resto >>> [2, 3] \end{verbatim} En este caso, no se modifica la lista original. Puede estar preguntándose si un cambio sobre \texttt{rest} afectará a \texttt{numbers}. Pruébelo usted mismo para averiguarlo. \begin{quote} \emph{Como ejercicio, escriba una función llamada} \texttt{\emph{clone\_list}} \emph{que tome como parámetro una lista y devuelva una lista clonada.} \end{quote} \section{Listas anidadas} \label{nested lists} \index{listas anidadas} \index{listas!anidadas} Hemos visto un ejemplo de lista anidada: \begin{verbatim} >>> lista = ["hola", 2.0, 5, [10, 20]] \end{verbatim} El tercer elemento de esta lista es, a su vez, una lista. Si imprimimos \texttt{lista{[}3{]}}, obtendremos \texttt{{[}10, 20{]}}. Para extraer los elementos de la lista anidada, podemos proceder en dos pasos: \begin{verbatim} >>> elt = lista[3] >>> elt[0] 10 \end{verbatim} O podemos combinarlos: \begin{verbatim} >>> lista[3][1] 20 \end{verbatim} Es común usar listas anidadas para representar matrices. Por ejemplo, la matriz \vspace{0.1in} \centerline{\includegraphics{matrix.eps} } \vspace{0.1in} puede ser representada \begin{verbatim} >>> matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] \end{verbatim} Esto es, \texttt{matriz} es una lista con tres elementos, siendo cada elemento una fila de la matriz. Podemos elegir una fila entera de la matriz de la forma normal. \begin{verbatim} >>> matriz[1] [4, 5, 6] \end{verbatim} O tomar sólo un elemento de la matriz usando la forma de doble índice. \begin{verbatim} >>> matriz[1][1] 5 \end{verbatim} El primer índice escoge la fila y el segundo la columna. Aunque esta manera de representar matrices es común, no es la única posibilidad. Una pequeña variación consiste en usar una lista de columnas en lugar de flas. En el siguiente capítulo veremos una alternativa más radical usando un diccionario. \section{Glosario} \begin{description} \item [lista:]Una colección de objetos con nombre, en la que cada objeto es identificado por un índice. \item [índice:]Una variable o valor enteros que se usan para indicar un elemento de una lista. \item [secuencia:]Cualquier tipo de datos que consita en un conjunto ordenado de elementos, con cada elemento identificado por un índice. Los tres tipos de secuencias de Python son \texttt{cadenas}, \texttt{listas}, y \texttt{tuplas}. \item [elemento:]Uno de los valores de una lista (u otra secuencia). El operador \texttt{{[}{]}} escoge elementos de una lista. \item [lista~anidada:]Una lista que es elemento de otra lista. \item [recorrido~de~lista:]Acceso secuencial a cada elemento de una lista. \item [objeto:]Una cosa a la que se puede referir una variable. \item [alias:]Múltiples variables que contienen referencias al mismo objeto. \index{lista} \index{índice} \index{sequencia} \index{elemento} \index{lista anidada} \index{recorrido de lista} \index{objeto} \index{alias}\end{description} \end{document}


Next Up Previous Hi Index