viernes, 29 de septiembre de 2017

Curso de introducción a python aplicado a la adquisición de datos de audio Sesion 1 a 4

Curso de introducción a python aplicado a la adquisición de datos de audio


Grupo de Estudio en Modelamiento Matemático 
Computo Científico
Alexander Arias
Septiembre de 2017

Sesión 1. Introducción a Python y PyCharm
https://cloud.mail.ru/public/LV98/5uZTAsZbX

Sesión 2. Operadores Básicos en Consola y primera aplicación con entrada de datos en PyCharm
https://cloud.mail.ru/public/KJoA/5cJU8pA5f

Sesión 3. Listas, Strings y Operaciones básicas con Strings
https://cloud.mail.ru/public/3aUt/jv8oBnwgY

Sesión 4. Diccionarios, Condicionales, Excepciones y Loops
https://cloud.mail.ru/public/MdPt/SjxzQ1wfC

miércoles, 27 de septiembre de 2017

35 Sonidos de instrumentos en formato wav y mp3 - 35 Звуки инструмента в формате wav и mp3


https://ccrma.stanford.edu/~jos/pasp/Sound_Examples.html
35 Sonidos de instrumentos en formato wav y mp3

 35 Звуки инструмента в формате wav и mp3

 Sound Examples


lunes, 25 de septiembre de 2017

viernes, 22 de septiembre de 2017

Programa en Python para capturar y graficar el audio desde un microfono de una diadema en el pc

#Programa en Python para capturar y graficar el audio desde un microfono de una diadema en el pc

import pyaudio
import os
import struct
import numpy as np
import matplotlib.pyplot as plt
import time
from tkinter import TclError
from matplotlib import style

# use this backend to display in separate Tk window


# constants
CHUNK = 1024             # samples per frame
FORMAT = pyaudio.paInt16     # audio format (bytes per sample?)
CHANNELS = 1                 # single channel for microphone
RATE = 44100                 # samples per second

style.use('dark_background')
# create matplotlib figure and axes
fig, ax = plt.subplots(1, figsize=(11, 7))

# pyaudio class instance
p = pyaudio.PyAudio()

# stream object to get data from microphone
stream = p.open(
    format=FORMAT,
    channels=CHANNELS,
    rate=RATE,
    input=True,
    output=True,
    frames_per_buffer=CHUNK
)

# variable for plotting
x = np.arange(0, 2 * CHUNK, 2)

# create a line object with random data
line, = ax.plot(x, np.random.rand(CHUNK), '-', lw=1)

# basic formatting for the axes
ax.set_title('AUDIO WAVEFORM')
ax.set_xlabel('samples')
ax.set_ylabel('amplitud')
ax.set_ylim(0, 255)
ax.set_xlim(0, 2 * CHUNK)
plt.setp(ax, xticks=[0, CHUNK, 2 * CHUNK], yticks=[0, 128, 255])


# show the plot
plt.show(block=False)

print('stream started')

# for measuring frame rate
frame_count = 0
start_time = time.time()

while True:
   
    # binary data
    data = stream.read(CHUNK) 
   
    # convert data to integers, make np array, then offset it by 127
    data_int = struct.unpack(str(2 * CHUNK) + 'B', data)
   
    # create np array and offset by 128
    data_np = np.array(data_int, dtype='b')[::2] + 128
   
    line.set_ydata(data_np)
   
    # update figure canvas
    try:
        fig.canvas.draw()
        fig.canvas.flush_events()
        frame_count += 1
       
    except TclError:
       
        # calculate average frame rate
        frame_rate = frame_count / (time.time() - start_time)
       
        print('stream stopped')
        print('average frame rate = {:.0f} FPS'.format(frame_rate))
        break

EL LIBRO Jorge Luis Borges

EL LIBRO
Jorge Luis Borges

De los diversos instrumentos del hombre, el más asombroso es, sin duda, el libro. Los demás son extensiones de su cuerpo. El microscopio, el telescopio, son extensiones de su vista; el teléfono es extensión de la voz; luego tenemos el arado y la espada, extensiones de su brazo. Pero el libro es otra cosa: el libro es una extensión de la memoria y de la imaginación.
En César y Cleopatra de Shaw, cuando se habla de la biblioteca de Alejandría se dice que es la memoria de la humanidad. Eso es el libro y es algo más también, la imaginación. Porque, ¿qué es nuestro pasado sino una serie de sueños? ¿Qué diferencia puede haber entre recordar sueños y recordar el pasado? Esa es la función que realiza el libro.
Yo he pensado, alguna vez, escribir una historia del libro. No desde el punto de vista físico. No me interesan los libros físicamente (sobre todo los libros de los bibliófilos, que suelen ser desmesurados), sino las diversas valoraciones que el libro ha recibido. He sido anticipado por Spengler, en su Decadencia de Occidente, donde hay páginas preciosas sobre el libro. Con alguna observación personal, pienso atenerme a lo que dice Spengler.
Los antiguos no profesaban nuestro culto del libro —cosa que me sorprende; veían en el libro un sucedáneo de la palabra oral. Aquella frase que se cita siempre: Scripta manent, verba volant, no significa que la palabra oral sea efímera, sino que la palabra escrita es algo duradero y muerto. En cambio, la palabra oral tiene algo de alado, de liviano; alado y sagrado, como dijo Platón. Todos los grandes maestros de la humanidad han sido, curiosamente, maestros orales.
Tomaremos el primer caso: Pitágoras. Sabemos que Pitágoras no escribió deliberadamente. No escribió porque no quiso atarse a una palabra escrita. Sintió, sin duda, aquello de que la letra mata y el espíritu vivifica, que vendría después en la Biblia. El debió sentir eso, no quiso atarse a una palabra escrita; por eso Aristóteles no habla nunca de Pitágoras, sino de los pitagóricos. Nos dice, por ejemplo, que los pitagóricos profesaban la creencia, el dogma, del eterno retorno, que muy tardíamente descubriría Nietzsche. Es decir, la idea del tiempo cíclico, que fue refutada por San Agustín en La ciudad de Dios. San Agustín dice con una hermosa metáfora que la cruz de Cristo nos salva del laberinto circular de los estoicos. La idea de un tiempo cíclico fue rozada también por Hume, por Blanqui... y por tantos otros.
Pitágoras no escribió voluntariamente, quería que su pensamiento viviese más allá de su muerte corporal, en la mente de sus discípulos. Aquí vino aquello de (yo no sé griego, trataré de decirlo en latín) Magister dixit (el maestro lo ha dicho). Esto no significa que estuvieran atados porque el maestro lo había dicho; por el contrario, afirma la libertad de seguir pensando el pensamiento inicial del maestro.
No sabemos si inició la doctrina del tiempo cíclico, pero sí sabemos que sus discípulos la profesaban. Pitágoras muere corporalmente y ellos, por una suerte de transmigración —esto le hubiera gustado a Pitágoras— siguen pensando y repensando su pensamiento, y cuando se les reprocha el decir algo nuevo, se refugian en aquella fórmula: el maestro lo ha dicho (Magister dixit).
Pero tenemos otros ejemplos. Tenemos el alto ejemplo de Platón, cuando dice que los libros son como efigies (puede haber estado pensando en esculturas o en cuadros), que uno cree que están vivas, pero si se les pregunta algo no contestan. Entonces, para corregir esa mudez de los libros, inventa el diálogo platónico. Es decir, Platón se multiplica en muchos personajes: Sócrates, Gorgias y los demás. También podemos pensar que Platón quería consolarse de la muerte de Sócrates pensando que Sócrates seguía viviendo. Frente a todo problema él se decía: ¿qué hubiera dicho Sócrates de esto? Así, de algún modo, fue la inmortalidad de Sócrates, quien no dejó nada escrito, y también un maestro oral. De Cristo sabemos que escribió una sola vez algunas palabras que la arena se encargó de borrar. No escribió otra cosa que sepamos. El Buda fue también un maestro oral; quedan sus prédicas. Luego tenemos una frase de San Anselmo: Poner un libro en manos de un ignorante es tan peligroso como poner una espada en manos de un niño. Se pensaba así de los libros. En todo Oriente existe aún el concepto de que un libro no debe revelar las cosas; un libro debe, simplemente, ayudarnos a descubrirlas. A pesar de mi ignorancia del hebreo, he estudiado algo de la Cábala y he leído las versiones inglesas y alemanas del Zohar (El libro del esplendor), El Séfer Yezira (El libro de las relaciones). Sé que esos libros no están escritos para ser entendidos, están hechos para ser interpretados, son acicates para que el lector siga el pensamiento. La antigüedad clásica no tuvo nuestro respeto del libro, aunque sabemos que Alejandro de Macedonia tenía bajo su almohada la Ilíada y la espada, esas dos armas. Había gran respeto por Homero, pero no se lo consideraba un escritor sagrado en el sentido que hoy le damos a la palabra. No se pensaba que la Ilíada y la Odisea fueran textos sagrados, eran libros respetados, pero también podían ser atacados.
Platón pudo desterrar a los poetas de su República sin caer en la sospecha de herejía. De estos testimonios de los antiguos contra el libro podemos agregar uno muy curioso de Séneca. En una de sus admirables epístolas a Lucilio hay una dirigida contra un individuo muy vanidoso, de quien dice que tenía una biblioteca de cien volúmenes; y quién —se pregunta Séneca— puede tener tiempo para leer cien volúmenes. Ahora, en cambio, se aprecian las bibliotecas numerosas.
En la antigüedad hay algo que nos cuesta entender, que no se parece a nuestro culto del libro. Se ve siempre en el libro a un sucedáneo de la palabra oral, pero luego llega del Oriente un concepto nuevo, del todo extraño a la antigüedad clásica: el del libro sagrado. Vamos a tomar dos ejemplos, empezando por el más tardío: los musulmanes. Estos piensan que el Corán es anterior a la creación, anterior a la lengua árabe; es uno de los atributos de Dios, no una obra de Dios; es como su misericordia o su justicia. En el Corán se habla en forma asaz misteriosa de la madre del libro. La madre del libro es un ejemplar del Corán escrito en el cielo. Vendría a ser el arquetipo platónico del Corán, y ese mismo libro —lo dice el Corán—, ese libro está escrito en el cielo, que es atributo de Dios y anterior a la creación. Esto lo proclaman los sulems o doctores musulmanes.
Luego tenemos otros ejemplos más cercanos a nosotros: la Biblia o, más concretamente, la Torá o el Pentateuco. Se considera que esos libros fueron dictados por el Espíritu Santo. Esto es un hecho curioso: la atribución de libros de diversos autores y edades a un solo espíritu; pero en la Biblia misma se dice que el Espíritu sopla donde quiere. Los hebreos tuvieron la idea de juntar diversas obras literarias de diversas épocas y de formar con ellas un solo libro, cuyo título es Torá (Biblia en griego). Todos estos libros se atribuyen a un solo autor: el Espíritu.
A Bernard Shaw le preguntaron una vez si creía que el Espíritu Santo había escrito la Biblia. Y contestó: Todo libro que vale la pena de ser releído ha sido escrito por el Espíritu. Es decir, un libro tiene que ir más allá de la intención de su autor. La intención del autor es una pobre cosa humana, falible, pero en el libro tiene que haber más. El Quijote, por ejemplo, es más que una sátira de los libros de caballería. Es un texto absoluto en el cual no interviene, absolutamente para nada, el azar.
Pensemos en las consecuencias de esta idea. Por ejemplo, si yo digo:

Corrientes aguas, puras, cristalinas,
árboles que os estáis mirando en ellas
verde prado, de fresca sombra lleno

es evidente que los tres versos constan de once sílabas. Ha sido querido por el autor, es voluntario.
 Pero, qué es eso comparado con una obra escrita por el Espíritu, qué es eso comparado con el concepto de la Divinidad que condesciende a la literatura y dicta un libro. En ese libro nada puede ser casual, todo tiene que estar justificado, tienen que estar justificadas las letras. Se entiende, por ejemplo, que el principio de la Biblia: Bereshit baraelohim comienza con una B porque eso corresponde a bendecir. Se trata de un libro en el que nada es casual, absolutamente nada. Eso nos lleva a la Cábala, nos lleva al estudio de las letras, a un libro sagrado dictado por la divinidad que viene a ser lo contrario de lo que los antiguos pensaban. Estos pensaban en la musa de modo bastante vago.
Canta, musa, la cólera de Aquiles, dice Homero al principio de la Ilíada. Ahí, la musa corresponde a la inspiración. En cambio, si se piensa en el Espíritu, se piensa en algo más concreto y más fuerte: Dios, que condesciende a la literatura. Dios, que escribe un libro; en ese libro nada es casual: ni el número de las letras ni la cantidad de sílabas de cada versículo, ni el hecho de que podamos hacer juegos de palabras con las letras, de que podamos tomar el valor numérico de las letras. Todo ha sido ya considerado.
El segundo gran concepto del libro —repito— es que pueda ser una obra divina. Quizá esté más cerca de lo que nosotros sentimos ahora que de la idea del libro que tenían los antiguos: es decir, un mero sucedáneo de la palabra oral. Luego decae la creencia en un libro sagrado y es reemplazada por otras creencias. Por aquella, por ejemplo, de que cada país está representado por un libro. Recordemos que los musulmanes denominan a los israelitas, la gente del libro; recordemos aquella frase de Heinrich Heine sobre aquella nación cuya patria era un libro: la Biblia, los judíos. Tenemos entonces un nuevo concepto, el de que cada país tiene que ser representado por un libro; en todo caso, por un autor que puede serlo de muchos libros.
Es curioso —no creo que esto haya sido observado hasta ahora— que los países hayan elegido individuos que no se parecen demasiado a ellos. Uno piensa, por ejemplo, que Inglaterra hubiera elegido al doctor Johnson como representante; pero no, Inglaterra ha elegido a Shakespeare, y Shakespeare es —digámoslo así— el menos inglés de los escritores ingleses. Lo típico de Inglaterra es el understatement, es el decir un poco menos de las cosas. En cambio, Shakespeare tendía a la hipérbole en la metáfora, y no nos sorprendería nada que Shakespeare hubiera sido italiano o judío, por ejemplo.
Otro caso es el de Alemania; un país admirable, tan fácilmente fanático, elige precisamente a un hombre tolerante, que no es fanático, y a quien no le importa demasiado el concepto de patria; elige a Goethe. Alemania está representada por Goethe.
En Francia no se ha elegido un autor, pero se tiende a Hugo. Desde luego, siento una gran admiración por Hugo, pero Hugo no es típicamente francés. Hugo es extranjero en Francia; Hugo, con esas grandes decoraciones, con esas vastas metáforas, no es típico de Francia.
Otro caso aún más curioso es el de España. España podría haber sido representada por Lope, por Calderón, por Quevedo. Pues no. España está representada por Miguel de Cervantes. Cervantes es un hombre contemporáneo de la Inquisición, pero es tolerante, es un hombre que no tiene ni las virtudes ni los vicios españoles.
Es como si cada país pensara que tiene que ser representado por alguien distinto, por alguien que puede ser, un poco, una suerte de remedio, una suerte de triaca, una suerte de contraveneno de sus defectos. Nosotros hubiéramos podido elegir el Facundo de Sarmiento, que es nuestro libro, pero no; nosotros, con nuestra historia militar, nuestra historia de espada, hemos elegido como libro la crónica de un desertor, hemos elegido el Martín Fierro, que si bien merece ser elegido como libro, ¿como pensar que nuestra historia está representada por un desertor de la conquista del desierto? Sin embargo, es así; como si cada país sintiera esa necesidad.
Sobre el libro han escrito de un modo tan brillante tantos escritores. Yo quiero referirme a unos pocos. Primero me referiré a Montaigne, que dedica uno de sus ensayos al libro. En ese ensayo hay una frase memorable: No hago nada sin alegría. Montaigne apunta a que el concepto de lectura obligatoria es un concepto falso. Dice que si él encuentra un pasaje difícil en un libro, lo deja; porque ve en la lectura una forma de felicidad.
Recuerdo que hace muchos años se realizó una encuesta sobre qué es la pintura. Le preguntaron a mi hermana Norah y contestó que la pintura es el arte de dar alegría con formas y colores. Yo diría que la literatura es también una forma de la alegría. Si leemos algo con dificultad, el autor ha fracasado. Por eso considero que un escritor como Joyce ha fracasado esencialmente, porque su obra requiere un esfuerzo.
Un libro no debe requerir un esfuerzo, la felicidad no debe requerir un esfuerzo. Pienso que Montaigne tiene razón. Luego enumera los autores que le gustan. Cita a Virgilio, dice preferir las Geórgicas a la Eneida; yo prefiero la Eneida, pero eso no tiene nada que ver. Montaigne habla de los libros con pasión, pero dice que aunque los libros son una felicidad, son, sin embargo, un placer lánguido.
Emerson lo contradice —es el otro gran trabajo sobre los libros que existe—. En esa conferencia, Emerson dice que una biblioteca es una especie de gabinete mágico. En ese gabinete están encantados los mejores espíritus de la humanidad, pero esperan nuestra palabra para salir de su mudez. Tenemos que abrir el libro, entonces ellos despiertan. Dice que podemos contar con la compañía de los mejores hombres que la humanidad ha producido, pero que no los buscamos y preferimos leer comentarios, críticas y no vamos a lo que ellos dicen.
Yo he sido profesor de literatura inglesa, durante veinte años, en la Facultad de Filosofía y Letras de la Universidad de Buenos Aires. Siempre les he dicho a mis estudiantes que tengan poca bibliografía, que no lean críticas, que lean directamente los libros; entenderán poco, quizá, pero siempre gozarán y estarán oyendo la voz de alguien. Yo diría que lo más importante de un autor es su entonación, lo más importante de un libro es la voz del autor, esa voz que llega a nosotros.
Yo he dedicado una parte de mi vida a las letras, y creo que una forma de felicidad es la lectura; otra forma de felicidad menor es la creación poética, o lo que llamamos creación, que es una mezcla de olvido y recuerdo de lo que hemos leído.
Emerson coincide con Montaigne en el hecho de que debemos leer únicamente lo que nos agrada, que un libro tiene que ser una forma de felicidad. Le debemos tanto a las letras. Yo he tratado más de releer que de leer, creo que releer es más importante que leer, salvo que para releer se necesita haber leído. Yo tengo ese culto del libro. Puedo decirlo de un modo que puede parecer patético y no quiero que sea patético; quiero que sea como una confidencia que les realizo a cada uno de ustedes; no a todos, pero sí a cada uno, porque todos es una abstracción y cada uno es verdadero.
Yo sigo jugando a no ser ciego, yo sigo comprando libros, yo sigo llenando mi casa de libros. Los otros días me regalaron una edición del año 1966 de la Enciclopedia de Brokhause. Yo sentí la presencia de ese libro en mi casa, la sentí como una suerte de felicidad. Ahí estaban los veintitantos volúmenes con una letra gótica que no puedo leer, con los mapas y grabados que no puedo ver; y sin embargo, el libro estaba ahí. Yo sentía como una gravitación amistosa del libro. Pienso que el libro es una de las posibilidades de felicidad que tenemos los hombres.
Se habla de la desaparición del libro; yo creo que es imposible. Se dirá qué diferencia puede haber entre un libro y un periódico o un disco. La diferencia es que un periódico se lee para el olvido, un disco se oye asimismo para el olvido, es algo mecánico y por lo tanto frívolo. Un libro se lee para la memoria.
El concepto de un libro sagrado, del Corán o de la Biblia, o de los Vedas —donde también se expresa que los Vedas crean el mundo—, puede haber pasado, pero el libro tiene todavía cierta santidad que debemos tratar de no perder. Tomar un libro y abrirlo guarda la posibilidad del hecho estético. ¿Qué son las palabras acostadas en un libro? ¿Qué son esos símbolos muertos? Nada absolutamente. ¿Qué es un libro si no lo abrimos? Es simplemente un cubo de papel y cuero, con hojas; pero si lo leemos ocurre algo raro, creo que cambia cada vez.
Heráclito dijo (lo he repetido demasiadas veces) que nadie baja dos veces al mismo río. Nadie baja dos veces al mismo río porque las aguas cambian, pero lo más terrible es que nosotros somos no menos fluidos que el río. Cada vez que leemos un libro, el libro ha cambiado, la connotación de las palabras es otra. Además, los libros están cargados de pasado.
He hablado en contra de la crítica y voy a desdecirme (pero qué importa desdecirme). Hamlet no es exactamente el Hamlet que Shakespeare concibió a principios del sigio XVII, Hamlet es el Hamlet de Coleridge, de Goethe y de Bradley. Hamlet ha sido renacido. Lo mismo pasa con el Quijote. Igual sucede con Lugones y Martínez Estrada, el Martín Fierro no es el mismo. Los lectores han ido enriqueciendo el libro.
Si leemos un libro antiguo es como si leyéramos todo el tiempo que ha transcurrido desde el día en que fue escrito y nosotros. Por eso conviene mantener el culto del libro. El libro puede estar lleno de erratas, podemos no estar de acuerdo con las opiniones del autor, pero todavía conserva algo sagrado, algo divino, no con respeto superticioso, pero sí con el deseo de encontrar felicidad, de encontrar sabiduría.
Eso es lo que quería decirles hoy.

Jorge Luis Borges, Borges oral. Alianza Editorial.

Algunos enlaces de trabajo de Python

Algunos enlaces de trabajo de Python


Ejercicios de condicionales y de loops
http://librosweb.es/libro/algoritmos_python/capitulo_4/ejercicios_5.html

web2py

Un resumen bueno de Python

http://web2py.com/books/default/chapter/36/02/el-lenguaje-python 

 

Listas en Python

https://gabrielacavalcante.gitbooks.io/python/content/listas.html


Temas de Python

https://gabrielacavalcante.gitbooks.io/python/content/listas.html


Pybonacci

Python y Ciencia

https://pybonacci.es/


Objetos en Python

24.1. turtle — Turtle graphics

 https://docs.python.org/3/library/turtle.html

 

 

Dibujos simples con turtle (Tortuga)

https://opentechschool.github.io/python-beginners/es_CL/simple_drawing.html

 

Tina es una turtle (tortuga). ¿Qué significa turtle ? Aquí, una tortuga es un object (objeto). Esto significa que el programador que ha escrito este código quiere que Tina se comporte de cierta manera. Como haz visto anteriormente, Tina va hacia forward (adelante), backward (atrás), left (izquierda), y right (derecha).

https://hourofpython.com/una-introduccion-visual-a-python/varias-tortugas/las-tortugas-son-objetos.html

 

Python Diccionario

http://www.w3ii.com/es/python/python_dictionary.html


Listas

http://progra.usm.cl/apunte/materia/listas.html


Hashing en Python

http://pythoncentral.io/hashing-strings-with-python/


Loop control statements

http://python-textbok.readthedocs.io/en/1.0/Loop_Control_Statements.html

 

Aprender python en linea

https://www.learnpython.org 

 

Listas y Tuplas

http://recursospython.com/guias-y-manuales/listas-y-tuplas/ 

 

Hash de texto en python; sha256 

http://www.pythondiario.com/2016/03/hash-en-python-sha256.html 


Hashing en Python

https://sites.google.com/site/programacioniiuno/temario/unidad-4---hashing


Python IF...ELIF...ELSE Statements

https://www.tutorialspoint.com/python/python_if_else.htm 

 

Excepciones en Python

http://librosweb.es/libro/algoritmos_python/capitulo_12/excepciones.html

 

Errores y excepciones

http://docs.python.org.ar/tutorial/2/errors.html 

 http://docs.python.org.ar/tutorial/3/errors.html 


Página para probar y competir en programación

https://www.urionlinejudge.com.br

 

 

 

 

 




Curso de introducción a python aplicado a la adquisición de datos de audio

Curso de introducción a python aplicado a la adquisición de datos de audio
 
https://profeitm.blogspot.com/2017/09/curso-de-introduccion-python-aplicado.html

lunes, 18 de septiembre de 2017

Álgebra Lineal en Python con NumPy (I): Operaciones básicas

Álgebra Lineal en Python con NumPy (I): Operaciones básicas

https://pybonacci.es/2012/06/07/algebra-lineal-en-python-con-numpy-i-operaciones-basicas/ 

 

Introducción

En esta entrada vamos a ver una introducción al Álgebra Lineal en Python con NumPy. En la mayoría de los artículos que hemos escrito hasta ahora en Pybonacci hemos tocado sin mencionarlos conceptos relativos al Álgebra Lineal: sin ir más lejos, el propio manejo de matrices o la norma de vectores. El lenguaje matricial es el punto de partida para una enorme variedad de desarrollos físicos y matemáticos, y por eso le vamos a dedicar un apartado especial para repasar las posibilidades que ofrece el paquete NumPy.
  1. Operaciones básicas
  2. Sistemas, autovalores y descomposiciones
En esta entrada se ha usado python 2.7.3 y numpy 1.6.1 y es compatible con python 3.2.3

Arrays y matrices

Como ya comentamos hace tiempo en nuestra introducción a Python, el paquete NumPy introdujo los arrays N-dimensionales, que no son más que colecciones homogéneas de elementos indexados usando N elementos. Los hemos utilizado constantemente usando las funciones de creación de arrays:
In [1]: import numpy as np
In [2]: np.array([1, 2, 3])  # Array de una lista
Out[2]: array([1, 2, 3])
In [3]: np.arange(5)  # Array de 5 enteros contando el 0
Out[3]: array([0, 1, 2, 3, 4])
In [4]: np.zeros((2, 3))  # Array de ceros de 2x3
Out[4]:
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
In [5]: np.linspace(0.0, 1.0, 5)  # Discretización de [0, 1] con 5 puntos
Out[5]: array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ])
Además de los arrays, con NumPy también podemos manejar matrices. Aunque parecen lo mismo, se utilizan de manera distinta; si alguien quiere investigar las diferencias, puede consultar la página NumPy para usuarios de MATLAB (en inglés).

Nota: Aunque la traducción al castellano de array sería precisamente vector, para evitar confusión voy a seguir utilizando la palabra inglesa, como he venido haciendo desde que se creó el blog.
Si queremos matrices, entonces hemos de usar la función matrix:
In [17]: v2 = np.matrix([0, 1, 2, 3])
In [18]: v2
Out[18]: matrix([[0, 1, 2, 3]])
In [19]: np.transpose(v2)
Out[19]:
matrix([[0],
        [1],
        [2],
        [3]])
In [20]: v2.T
Out[20]:
matrix([[0],
        [1],
        [2],
        [3]])
In [27]: np.matrix("""  # Para los nostálgicos
   ....: 1, 2;
   ....: 3, 4
   ....: """)
Out[27]:
matrix([[1, 2],
        [3, 4]])
Las ventajas de usar matrices en el fondo son muy pocas y además la mayoría de funciones de NumPy maneja arrays, así que tendrías que convertir entre ambos tipos constantemente. Hoy mostraremos brevemente el uso de las matrices también, pero mejor utilizar arrays y olvidarse 😉

Operaciones básicas, expansión

Suma

La suma de arrays y de matrices es igual: se realiza elemento a elemento. El producto por un escalar tampoco tiene misterio:
In [1]: import numpy as np
In [2]: a = np.array([[1, 2], [3, 4]])
In [3]: a + a
Out[3]:
array([[2, 4],
       [6, 8]])
In [4]: m = np.matrix([[1, 2], [3, 4]])
In [5]: m + m
Out[5]:
matrix([[2, 4],
        [6, 8]])
In [6]: a + m  # Podemos sumar arrays y matrices
Out[6]:
matrix([[2, 4],
        [6, 8]])
In [7]: 2 * a  # Producto por un escalar
Out[7]:
array([[2, 4],
       [6, 8]])
In [8]: -m
Out[8]:
matrix([[-1, -2],
        [-3, -4]])

Expansión o «broadcasting»

Si los objetos que estamos operando no tienen las mismas dimensiones, NumPy puede adaptar algunas de ellas para completar la operación. Esto se denomina broadcasting en inglés, y a falta de una traducción mejor y a menos que alguien tenga algo que objetar lo voy a denominar «expansión». Porque yo lo valgo.
NumPy alinea los arrays a la derecha y empieza a comprobar las dimensiones por el final. Si son todas compatibles realiza la operación, y si no lanza un error. Dos dimensiones son compatibles si
  1. Son iguales, o
  2. Una de ellas es 1.
Si los objetos no tienen el mismo número de dimensiones, se asume que las restantes son 1. Si dos dimensiones son distintas pero compatibles, la menor se expande hasta tener el tamaño de la mayor. Vamos a ver un par de ejemplos:
In [29]: c = np.zeros((3, 3))
In [30]: c
Out[30]:
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
In [31]: c.shape
Out[31]: (3, 3)
In [32]: n = np.array([1, 2, 3])
In [33]: n
Out[33]: array([1, 2, 3])
In [34]: n.shape
Out[34]: (3,)
In [35]: n + c  # Se expande la primera dimensión de n
Out[35]:
array([[ 1.,  2.,  3.],
       [ 1.,  2.,  3.],
       [ 1.,  2.,  3.]])

In [61]: xx = np.arange(4)
In [62]: yy = np.arange(4).reshape((4, 1))
In [63]: xx
Out[63]: array([0, 1, 2, 3])
In [64]: xx.shape
Out[64]: (4,)
In [65]: yy
Out[65]:
array([[0],
       [1],
       [2],
       [3]])
In [66]: yy.shape
Out[66]: (4, 1)
In [67]: xx + yy * 1j  # Se expanden la segunda dimensión de y y la primera de x
Out[67]:
array([[ 0.+0.j,  1.+0.j,  2.+0.j,  3.+0.j],
       [ 0.+1.j,  1.+1.j,  2.+1.j,  3.+1.j],
       [ 0.+2.j,  1.+2.j,  2.+2.j,  3.+2.j],
       [ 0.+3.j,  1.+3.j,  2.+3.j,  3.+3.j]])
Como podéis ver, esto abre un mundo de posibilidades. Si queréis ampliarlas, podéis consultar el material de donde he sacado esto en la página Broadcasting de la guía del usuario de NumPy.

Producto

En el producto es donde surgen las diferencias fundamentales entre arrays y matrices. Mientras que con los arrays el producto se hace elemento a elemento (y si las dimensiones no coinciden se expanden como hemos visto antes), el producto de matrices tiene, como ya sabemos, una definición totalmente distinta.
Para el producto matricial:
In [69]: a = np.array([[1, 0], [2, -1]])
In [70]: a
Out[70]:
array([[ 1,  0],
       [ 2, -1]])
In [71]: np.dot(a, a)
Out[71]:
array([[1, 0],
       [0, 1]])
In [72]: m = np.matrix('1 0; 2 -1')
In [73]: m
Out[73]:
matrix([[ 1,  0],
        [ 2, -1]])
In [74]: m * m
Out[74]:
matrix([[1, 0],
        [0, 1]])
Y para el producto elemento a elemento
In [80]: a
Out[80]:
array([[ 1,  0],
       [ 2, -1]])
In [81]: a * a
Out[81]:
array([[1, 0],
       [4, 1]])
In [82]: m
Out[82]:
matrix([[ 1,  0],
        [ 2, -1]])
In [83]: np.multiply(m, m)
Out[83]:
matrix([[1, 0],
        [4, 1]])
Nótese que con las matrices el producto «por defecto» es el producto tal y como lo conocemos en Álgebra Lineal.
Ya hemos utilizado la función dot, que realiza un producto escalar entre sus dos argumentos, en este caso generalizado para matrices. NumPy también ofrece la función inner, que no es más que producto interior. Matemáticamente, el producto escalar es un caso particular del interior; en NumPy, ambos son idénticos para objetos de dimensión menor o igual que 2. Para arrays de dimensiones mayores que 2, se diferencian en las dimensiones sobre las que se suma.
Con NumPy podemos calcular también el producto vectorial y el producto exterior de dos vectores, utilizando las funciones cross y outer respectivamente:
In [102]: u = np.arange(3)
In [103]: v = 1 + np.arange(3)  # ¡Expansión sobre el 1!
In [104]: u
Out[104]: array([0, 1, 2])
In [105]: v
Out[105]: array([1, 2, 3])
In [106]: np.cross(u, v)  # Producto vectorial
Out[106]: array([-1,  2, -1])
In [107]: np.outer(u, v)  # Producto exterior
Out[107]:
array([[0, 0, 0],
       [1, 2, 3],
       [2, 4, 6]])

Norma y determinante

NumPy ofrece también diversas funciones para calcular la norma y el determinante de un array. Para calcular el determinante de un array de dimensión 2 utilizamos la función linalg.det. También podemos conocer la traza con la función trace:
In [111]: a
Out[111]:
array([[ 1,  0],
       [ 2, -1]])
In [112]: np.linalg.det(a)
Out[112]: -1.0
In [113]: np.trace(a)
Out[113]: 0
Con NumPy podemos obtener también la norma de un array de cualquier dimensión y el número de condición de un array bidimensional. Para ello utilizamos las funciones linalg.norm y linalg.cond respectivamente, que aceptan un segundo argumento: el tipo de norma utilizado. Así, podemos conocer la norma-2 de un vector ||v||2 o la norma infinito o del supremo de una matriz ||A||infty. Para una lista completa, puedes consultar la documentación.
In [121]: a
Out[121]:
array([[ 1,  0],
       [ 2, -1]])
In [122]: np.linalg.norm(a)
Out[122]: 2.4494897427831779
In [123]: np.linalg.norm(a, np.inf)
Out[123]: 3
In [124]: np.linalg.norm(a, 1)
Out[124]: 3
In [125]: v
Out[125]: array([1, 2, 3])
In [126]: np.linalg.norm(v)
Out[126]: 3.7416573867739413
In [127]: np.linalg.norm(v, np.inf)
Out[127]: 3
In [128]: np.linalg.norm(v, 1)
Out[128]: 6
In [129]: np.linalg.norm(v, -np.inf)
Out[129]: 1
In [130]: np.linalg.cond(a)
Out[130]: 5.828427124746189
In [131]: np.linalg.cond(a, np.inf)
Out[131]: 9.0

Convenio de Einstein

Finalmente, y como regalo a los que hayan llegado hasta aquí abajo, os enseñamos que con NumPy podemos utilizar el convenio de sumación de Einstein, utilizando la función einsum. Para los que conozcan un poco de álgebra tensorial, esta función les va a encantar: con ella podemos hacer todo lo que hemos visto anteriormente y mucho más. En la documentación viene explicado detenidamente cómo utilizarla y hay unos cuantos ejemplos; vamos a ver algunos:
In [135]: a
Out[135]:
array([[ 1,  0],
       [ 2, -1]])
In [136]: np.trace(a)
Out[136]: 0
In [137]: np.einsum('ii', a)  # Traza
Out[137]: 0
In [138]: np.diag(a)
Out[138]: array([ 1, -1])
In [139]: np.einsum('ii -> i', a)  # Diagonal
Out[139]: array([ 1, -1])
In [140]: np.dot(a, a)
Out[140]:
array([[1, 0],
       [0, 1]])
In [142]: np.einsum('ij, jk', a, a)  # Producto matricial
Out[142]:
array([[1, 0],
       [0, 1]])
In [143]: u = np.array([1, -2])
In [144]: u
Out[144]: array([ 1, -2])
In [145]: np.dot(a, u)
Out[145]: array([1, 4])
In [146]: np.einsum('ij, j', a, u)  # Matriz por vector
Out[146]: array([1, 4])
In [147]: np.dot(u, u)
Out[147]: 5
In [151]: np.einsum('i, i', u, u)  # Producto escalar por sí mismo
Out[151]: 5
In [153]: np.outer(u, u)
Out[153]:
array([[ 1, -2],
       [-2,  4]])
In [154]: np.einsum('i, j', u, u)  # Producto exterior
Out[154]:
array([[ 1, -2],
       [-2,  4]])
Las posibilidades que esto ofrece son enormes. Puedes probar a jugar con tensores de mayor orden, como por ejemplo el símbolo de Levi-Civita.
https://gist.github.com/2689795

 

Listas en Python

Listas en Python

https://panda.ime.usp.br/pensepy/static/pensepy/09-Listas/listas.html


  1. Listas

    Uma lista (list) em Python é uma sequência ou coleção ordenada de valores. Cada valor na lista é identificado por um índice. O valores que formam uma lista são chamados elementos ou itens. Listas são similares a strings, que são uma sequência de caracteres, no entanto, diferentemente de strings, os itens de uma lista podem ser de tipos diferentes.

    Valores em uma lista

    Existem várias maneiras de se criar uma nova lista. A maneira mais simples é envolver os elementos da lista por colchetes ( [ e ]).
    [10, 20, 30, 40]
    ["spam", "bungee", "swallow"]
    
    O primeiro exemplo é uma lista de quatro inteiros. O segundo é uma lista de três strings. Como dissemos anteriormente, os elementos de uma lista não precisam ser do mesmo tipo. A lista a seguir contém um string, um float, um inteiro e uma outra lista.
    ["oi", 2.0, 5, [10, 20]]
    
    Um lista em uma outra lista é dita aninhada (nested) e a lista mais interna é chamada frequentemente de sublista (sublist). Finalemente, existe uma lista especial que não contém elemento algum. Ela é chamada de lista vazia e é denotada por [].
    Como você esperaria, podemos também atribuir listas a variáveis e termos listas como parâmetro de funções.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    vocabulario = ["iteracao", "selecao", "controle"]
    numeros = [17, 123]
    vazia = []
    lista_mista = ["ola", 2.0, 5*2, [10, 20]]
     
    print(numeros)
    print(lista_mista)
    nova_lista = [numeros, vocabulario]
    print(nova_lista)
     
     
    (chp09_01)

    Teste seu entendimento
    9.1.1: Uma lista só pode conter números inteiros?


    Comprimento de uma lista

    Da mesma forma que occore com strings, a função len retorna o comprimento de uma lista (o número de elementos na lista). Entretanto, como listas podem conter itens que são listas, é importante notar que len somente retorna o comprimento da lista mais externa. Em outras palavras, sublistas de uma lista são consideradas como sendo um elemento simples quando contamos o comprimento da lista.
    1
    2
    3
    4
    5
    uma_lista =  ["ola", 2.0, 5, [10, 20]]
    print(len(uma_lista))
    print(len(['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]))
     
     
    (chp09_01a)

    Teste seu entendimento
    9.2.1: O que é impresso pelo trecho de código a seguir?
    uma_lista = [3, 67, "gato", 3.14, False]
    print(len(uma_lista))
    


    9.2.2: O que é impresso pelo trecho de código a seguir?
    uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False]
    print(len(uma_lista))
    


    Acessando os elementos

    A sintaxe para acessar um elemento de uma lista é a mesma usada para acessar um caractere de um string. Nós usamos o operador de indexação ( [] – não confundir com a lista vazia). A expressão dentro dos conchetes especifica o índice. Lembrar que o índice do primeiro elemento é 0. Qualquer expressão que tenha como resultado um número inteiro pode ser usada como índice e como com strings, índices negativos indicarão elementos da direita para a esquerda ao invés de da esquerda para a direita.
    1
    2
    3
    4
    5
    6
    7
    numeros = [17, 123, 87, 34, 66, 8398, 44]
    print(numeros[2])
    print(numeros[9-8])
    print(numeros[-2])
    print(numeros[len(numeros)-1])
     
     
    (chp09_02)

    Teste seu entendimento
    9.3.1: O que é impresso pelo trecho de código a seguir?
    uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False]
    print(uma_lista[5])
    



    9.3.2: O que é impresso pelo trecho de código a seguir?
    uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False]
    print(uma_lista[2].upper())
    



    9.3.3: O que é impresso pelo trecho de código a seguir?
    uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False]
    print(uma_lista[2][0])
    




    Pertinência em uma Lista

    in e not in são operadores booleanos ou lógicos que testam a pertinência (membership) em uma sequência. Já usamos esses operadores com strings e eles também funcionam aqui.
    1
    2
    3
    4
    5
    6
    frutas = ["maca", "laranja", "banana", "cereja"]
     
    print("maca" in frutas)
    print("pera" in frutas)
     
     
    (chp09_4)

    Teste seu entendimento
    9.4.1: O que é impresso pelo trecho de código a seguir?
    uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False]
    print(3.14 in uma_lista)
    


    9.4.2: O que é impresso pelo trecho de código a seguir?
    uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False]
    print(57 in uma_lista)
    


    Concatenação e repetição

    Novamente, como com strings, o operador + concatena listas. Analogamente, o operador * repete os itens em uma lista um dado número de vezes.
    1
    2
    3
    4
    5
    6
    7
    8
    frutas = ["maca", "laranja", "banana", "cereja"]
    print([1, 2] + [3, 4])
    print(frutas + [6, 7, 8, 9])
     
    print([0] * 4)
    print([1, 2, ["ola", "adeus"]]*2)
     
     
    (chp09_5)

    É importante perceber que esses operadores criam novas listas a partir dos elementos da lista dada. Se você concatena uma lista com 2 itens com uma lista com 4 itens, você obterá uma nova lista com 6 itens (não uma lista com duas sublistas). Similarmente, repetição de uma lista de 2 itens 4 vezes resultará em uma lista com 8 itens.
    Uma maneira de fazermos isto mais claro é executar uma parte desses exemplos no codelens. A medida que cada passo do código é executado, você verá as variáveis sendo criadas e as listas as quais elas se referem. Preste atenção particularmente ao rótulo (tag) id que é mostrado depois do descritor do tipo de dado (list (id = 12))). Em Python o id corresponde a um único identificador para aquele objeto particular. Você pode dizer se são objetos diferentes através da comparação dos seus ids.

    1frutas = ["maca", "laranja", "banana", "cereja"]
    2num_lista = [6,7]
    3
    4nova_lista = frutas + num_lista
    5
    6zeros = [0] * 4
    Program terminated
    line that has just executed
    next line to execute
    Frames
    Global variables
    frutas
     
    num_lista
     
    nova_lista
     
    zeros
     
    Objects
    list
    0123
    "maca""laranja""banana""cereja"
    list
    01
    67
    list
    012345
    "maca""laranja""banana""cereja"67
    list
    0123
    0000
    (chp09_concatid)
    O comando nova_lista = frutas + num_lista cria uma nova lista de objetos com o contéudo da lista frutas seguido pelo conteúdo da lista num_lista. Podemos ver que está é uma lista nova olhando os ids. O id da nova_lista não e o mesmo que o das outras. É extremamente importante que você saiba quando está criando uma nova lista ou apenas alterando uma lista existente. Novamente, os ids podem ajudar nessa tarefa.
    Python possui uma função nativa (build-in) que recebe um objeto como argumento e retorna o seu id. A função é comvenientemente chamada de id e tem um único parâmetro, o objeto que você está interessado em descobrir o id. Você pode ver no examplo abaixo que o id real é usualmente um número inteiro muito grande (correspondente a um endereço na memória).
    >>> uma_lista = [4,5,6]
    >>> id(uma_lista)
    4300840544
    >>>
    
    Teste seu entendimento
    9.5.1: O que é impresso pelo trecho de código a seguir?
    uma_lista = [1, 3, 5]
    outra_lista = [2, 4, 6]
    print(uma_lista + outra_lista)
    




    9.5.2: O que é impresso pelo trecho de código a seguir?
    uma_lista = [1, 3, 5]
    print(uma_lista * 3)
    




    Fatias de listas

    A operação de fatiar (slice) que vimos com strings também pode ser aplicada sobre listas. Lembre que o primeiro índice indica o ponto do início da fatia e o segundo índice é um depois do final da fatia (o elemento com esse índice não faz parte da fatia).
    1
    2
    3
    4
    5
    6
    7
    uma_lista = ['a', 'b', 'c', 'd', 'e', 'f']
    print(uma_lista[1:3])
    print(uma_lista[:4])
    print(uma_lista[3:])
    print(uma_lista[:])
     
     
    (chp09_6)

    Teste seu entendimento
    9.6.1: O que é impresso pelo trecho de código a seguir?
    uma_lista = [3, 67, "gato", [56, 57, "cachorro"], [ ], 3.14, False]
    print(uma_lista[4:])
    



    Listas são mutáveis

    Diferentemente de strings, listas são mutáveis (mutable). Isto significa que podemos alterar um item em uma lista acessando-o diretamente como parte do comando de atribuição. Usando o operador e indexação (colchetes) à esquerda de um comando de atribuição, podemos atualizar um dos itens de uma lista.
    1
    2
    3
    4
    5
    6
    7
    8
    frutas = ["banana", "maca", "cereja"]
    print(frutas)
     
    frutas[0] = "pera"
    frutas[-1] = "laranja"
    print(frutas)
     
     
    (ch09_7)

    Uma atribuição a um elemento de uma lista é chamada de atribuição a um item (item assignment). Atribuição a itens não funciona com strings. Lembre-se que strings são imutáveis.
    Aqui está o mesmo exemplo com o codelens para que você possa executar comando após comando e veja as mudanças na lista de elementos.

    1frutas = ["banana", "maça", "cereja"]
    2
    3frutas[0]  = "pera"
    4frutas[-1] = "laranja"
    Step 1 of 3
    line that has just executed
    next line to execute
    Frames
    Objects
    (item_assign)
    Combinando uma atribuição com o operador de fatiamento podemos atualizar vários elementos de uma só vez.
    1
    2
    3
    4
    5
    uma_lista = ['a', 'b', 'c', 'd', 'e', 'f']
    uma_lista[1:3] = ['x', 'y']
    print(uma_lista)
     
     
    (ch09_8)

    Também podemosremover elementos de uma lista atribuindo a lista vazia a eles.
    1
    2
    3
    4
    5
    uma_lista = ['a', 'b', 'c', 'd', 'e', 'f']
    uma_lista[1:3] = []
    print(uma_lista)
     
     
    (ch09_9)

    Podemos inserir elementos em uma lista espremendo-os em uma fatia vazia na posição desejada.
    1
    2
    3
    4
    5
    6
    7
    uma_lista = ['a', 'd', 'f']
    uma_lista[1:1] = ['b', 'c']
    print(uma_lista)
    uma_lista[4:4] = ['e']
    print(uma_lista)
     
     
    (ch09_10)

    Teste seu entendimento
    9.7.1: O que é impresso pelo trecho de código a seguir?
    uma_lista = [4, 2, 8, 6, 5]
    uma_lista[2] = True
    print(uma_lista)
    



    Remoção em listas

    Usando fatiamento para remover elementos de uma lista pode ser complicado, e portanto propagador de erros. Python oferece uma maneira alternativa que é mais legível. O comando del remove um elemento de uma lista usando a sua posição.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    a = ['um', 'dois', 'três']
    del a[1]
    print(a)
     
    lista = ['a', 'b', 'c', 'd', 'e', 'f']
    del lista[1:5]
    print(lista)
     
     
    (ch09_11)

    Como você pode esperar, del também manipula índices negativos e produz um erro de execução se o índice estiver foram do intervalo da lista. Além disso, você pode usar uma fatia como argumento para del. Como é usual, fatias selecionam todos os elementos até, mas não incluindo, o segundo índice.

    Objetos e referências

    Se executamos as seguintes atribuições,
    a = "banana"
    b = "banana"
    
    sabemos que a e b farão referência ao string "banana". Entretanto, ainda não sabemos se eles se referem ao mesmo string.
    Existem duas possibilidades para o Python interpretar internamente essas atribuições:
    List illustration ou
    List illustration Em uma das interpretações a e b se referem a dois strings ou objetos diferentes que têm o mesmo valor. Na segunda interpretação, eles se referem ao mesmo objeto. Lembre-se que um objeto é uma valor ao qual uma variável pode se referir ou apontar.
    Já sabemos que objetos podem ser identificados usando seus identificadores que são únicos. Podemos também testar se dois nomes se referem ao mesmo objeto usando o operador is. O operador is retorna True se as duas referências são ao mesmo objeto. Em outras palavras, as referências são a mesma. Teste esse conceito com os exemplos acima.
    1
    2
    3
    4
    5
    6
    a = "banana"
    b = "banana"
     
    print(a is b)
     
     
    (chp09_is1)

    A resposta é True. Isto nos diz que ambos a e b se referem ao mesmo objeto, e que o segundo dos diagramas de referências descreve a relação. Como strings são imutáveis (immutable), Python optimiza recursos fazendo dois que se referem ao mesmo string se referirem ao mesmo objeto.
    Este não é o caso com listas. Considere o exemplo seguir. Aqui a e b se referem a duas listas diferentes, cada uma por acaso tem os mesmo elementos como valores.
    1
    2
    3
    4
    5
    6
    7
    8
    a = [81, 82, 83]
    b = [81, 82, 83]
     
    print(a is b)
     
    print(a == b)
     
     
    (chp09_is2)

    O diagrama de referências para este exemplo se parece com o seguinte.
    Reference diagram for equal different lists a e b tem o mesmo valor mas não se referem ao mesmo objeto.
    Existe ainda um outro ponto importante a ser notado a respeito desse diagrama de referências. O valor a é uma referência a uma coleção de referências (collection of references). Essas referências na realidade se referem a valores inteiros em uma lista. Em outras palavras, um lista é uma coleção de referências para objetos. É interessante que apesar de a e b serem duas listas distintas (duas coleções de diferentes de referências), o objeto inteiro 81 é compartilhado por ambos. Como strings, inteiros são também imutáveis portanto Python optimiza e permite que todos compartilhem o mesmo objeto.
    Aqui esta o exemplo no codelens. Preste atenção particularmente nos valores dos id.

    1a = [81, 82, 83]
    2b = [81, 82, 83]
    3
    4print(a is b)
    5print(a == b)
    Program terminated
    line that has just executed
    next line to execute
    Program output:
    Frames
    Global variables
    a
     
    b
     
    Objects
    list
    012
    818283
    list
    012
    818283
    (chp09_istrace)

    Apelidos (Aliasing)

    Como variáveis fazem referência a objetos, se atribuimos uma variável a outra, ambas as variáveis passam a fazer referência ao mesmo objeto.
    1
    2
    3
    4
    5
    a = [81, 82, 83]
    b = a
    print(a is b)
     
     
    (listalias1)

    Nesse caso, o diagrama de referências se parece com:
    State snapshot for multiple references (aliases) to a list Como a mesma lista tem dois nomes diferentes, a e b, dizemos que a lista tem apelidos (aliased). Mudanças feitas com um apelido afeta o outro. No exemplo do codelens a seguir, os ids de a e b são os mesmos depois da execução do comando de atribuição b = a.

    1a = [81, 82, 83]
    2b = [81, 82, 83]
    3
    4print(a == b)
    5print(a is b)
    6
    7b = a
    8print(a == b)
    9print(a is b)
    10
    11b[0] = 5
    12print(a)
    Program terminated
    line that has just executed
    next line to execute
    Program output:
    Frames
    Global variables
    a
     
    b
     
    Objects
    list
    012
    58283
    (chp09_is3)
    Apesar desse comportamento ser útil, ele é algumas vezes inesperado ou indesejável. Em geral, é mais seguro evitar apelidos (aliasing) quando você está trabalhando com objetos mutáveis. É evidente que com objetos imutáveis não há problema. Por isto, Python é livre para usar apelidos (alias) de strings e inteiros quando surge uma oportunidade para economizar espaço.
    Teste seu entendimento
    9.10.1: O que é impresso pelo trecho de código a seguir?
    lista_a = [4, 2, 8, 6, 5]
    lista_b = lista_a
    lista_b[3] = 999
    print(lista_a)
    


    Clonando listas

    Se desejamos modificar uma lista e também manter uma cópia da lista original, temos que ser capazes de fazer uma cópia da lista, não apenas da referência. Este processo é algumas vezes chamado de clonar (cloning), para evitar a ambiguidade da palavra cópia.
    A maneira mais fácil de clonarmos uma lista é usar o operador de fatiação.
    Tomar qualquer fatia de a cria uma nova lista. Para clonar uma lista basta tomarmos a fatia como sendo a lista toda.

    1a = [81, 82, 83]
    2
    3b = a[:]       # cria um clone com fatia
    4print(a == b)
    5print(a is b)
    6
    7b[0] = 5
    8
    9print(a)
    10print(b)
    Step 1 of 7
    line that has just executed
    next line to execute
    Program output:
    Frames
    Objects
    (chp09_is4)
    Agora estamos livres para modicar b sem nos preocuparmos com a. Note também que o id de b é diferente do id de a. Ela é uma lista completamente diferente.

    Repetições e referências

    Já vimos que o operador de repetição trabalho sobre strings e também sobre listas. Por exemplo.
    1
    2
    3
    4
    lista_original = [45, 76, 34, 55]
    print(lista_original*3)
     
     
    (repref1)

    Como uma lista, o operador de repetição cria cópias das referências. Apesar desse comportamento parecer simples, quando permitimos que uma lista ter referências a uma outra lista, podemos nos confrontar com alguns problemas sutis.
    Considere a seguinte extensão do exemplo anterior.
    1
    2
    3
    4
    5
    6
    7
    8
    lista_original = [45, 76, 34, 55]
    print(lista_original*3)
     
    lista_nova = [lista_original] * 3
     
    print(lista_nova)
     
     
    (repref2)

    lista_nova é uma lista com três referências para a lista_original que foram criadas pelo operador de repetição.
    Repetition of a nested list Agora, o que acontece se modificamos um valor da lista_original?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    lista_original = [45, 76, 34, 55]
     
    lista_nova = [lista_original] * 3
     
    print(lista_nova)
     
    lista_original[1] = 99
     
    print(lista_nova)
     
     
    (repref3)

    lista_nova mostra a mudança em três lugares. Isto pode ser facilmente entendido através do diagrama de referências, já que existe apenas uma lista_original. Logo, qualquer alteração na lista_original aparece em cada uma das três referências da nova_lista.
    Same reference Aqui está o mesmo exemplo no codelens. Execute o código passo a passo e preste particular atenção à execução do comando de atribuição lista_original[1] = 99.

    1lista_original = [45, 76, 34, 55]
    2
    3lista_nova = [lista_original] * 3
    4
    5print(lista_nova)
    6
    7lista_original[1] = 99
    8
    9print(lista_nova)
    Step 1 of 5
    line that has just executed
    next line to execute
    Program output:
    Frames
    Objects
    (reprefstep)
    Teste seu entendimento
    9.12.1: O que é impresso pelo trecho de código a seguir?
    lista_a = [4, 2, 8, 6, 5]
    lista_b = lista_a * 2
    lista_b[3] = 999
    print(lista_a)
    



    9.12.2: O que é impresso pelo trecho de código a seguir?
    lista_a = [4, 2, 8, 6, 5]
    lista_b = [lista_a] * 2
    lista_a[3] = 999
    print(lista_b)
    




    Métodos de listas

    O operador ponto também pode ser usado para acessar métodos nativos (built-in) de objetos que são listas. append é um método de listas que insere o argumento passado para ele no final da lista. O exemplo a seguir mostra vários outros métodos. Alguns deles são muito fáceis de serem compreendidos.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    minha_lista = []
    minha_lista.append(5)
    minha_lista.append(27)
    minha_lista.append(3)
    minha_lista.append(12)
    print(minha_lista)
     
    minha_lista.insert(1, 12)
    print(minha_lista)
    print(minha_lista.count(12))
     
    print(minha_lista.index(3))
    print(minha_lista.count(5))
     
    minha_lista.reverse()
    print(minha_lista)
     
    minha_lista.sort()
    print(minha_lista)
     
    minha_lista.remove(5)
    print(minha_lista)
     
    ultimo_item = minha_lista.pop()
    print(ultimo_item)
    print(minha_lista)
     
     
    (chp09_meth1)

    Existem duas maneiras de usar o método pop . A primeira, sem parâmetros, remove e retorna o último item da lista. Se for dado um argumento para a posição, pop remove e retorna o item da posição. De qualquer maneira a lista é alterada.
    A tabela a seguir mostra um resumo dos métodos de listas mostrados acima. Faça testes com esses métodos para ganhar uma melhor compreensão do que eles fazem.
    Método Parâmetros Resultado Descrição
    append item mutador Acrescenta um novo item no final da lista
    insert posição, item mutador Insere um novo item na posição dada
    pop nenhum híbrido Remove e returno o último item
    pop posição híbrido Remove e retorna o item da posição.
    sort nenhum mutador Ordena a lista
    reverse nenhum mutador Ordena a lista em ordem reversa
    index item retorna idx Retorna a posição da primeira ocorrência do item
    count item retorna ct Retorna o número de ocorrências do item
    remove item mutador Remove a primeira ocorrência do item
    Detalhes desses e de outros métodos podem ser vistos em Python Documentation.
    É importante notar que append, sort, e reverse retornam None. Isto significa que atribuira a minha_lista o resultado da ordenação de minha_lista resultará na perda da lista.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    minha_lista = []
    minha_lista.append(5)
    minha_lista.append(27)
    minha_lista.append(3)
    minha_lista.append(12)
    print(minha_lista)
     
    minha_lista = minha_lista.sort()   # possivel erro
    print(minha_lista)
     
     
    (chp09_meth2)

    Teste seu entendimento
    9.13.1:



    9.13.2: O que é impresso pelo trecho de código a seguir?
    uma_lista = [4, 2, 8, 6, 5]
    uma_lista.insert(2,True)
    uma_lista.insert(0,False)
    print(uma_lista)
    



    9.13.3:



    9.13.4:




    Scratch Editor

    Retorno a sistemas-L

    Retornemos aos sistemas-L que foram introduzidos na capítulo anterior e trataremos de uma característica interessante que usa listas.
    Suponha que temos a seguinte gramática:
    X
    X --> F[-X]+X
    F --> FF
    
    Este sistema-L é muito similar ao sistema-L já visto exceto que adicionamos uma mudança. Acrescentamos os caracteres ‘[‘ e ‘]’. O significado desses caracteres inclui uma nova dimensão bastante interessante ao nosso sistema-L. O caractere ‘[‘ indica que desejamos salvar o estado na nossa tartaruga, a saber a sua posição e sua sentido de tal maneira que possamos voltar a esta posição mais tarde. O ‘]’ diz a tartaruga para voltar para a última posição salva. A maneira que utilizaremos para realizar essas tarefas será através do uso de listas. Podemos salvar a sentido e posição de uma tartaruga como uma lista de 3 elementos [sentido, x, y] . A primeira posição da lista armazena a sentido, a segunda armazena a coordenada x e a terceira a coordenada y.
    Agora, se criarmos uma lista vazia e cada vez que virmos um ‘[‘ usarmos a função append para inserir no seu final a lista contendo [sentido, x, y] teremos um históricos das posições em que a tartaruga esteve. A última posição salva estará sempre no final da lista. Quando encontrarmos um ‘]’ no string, usamos a função pop para remover a última informação inserida na lista.
    Modifiquemos nossa função drawLsystem para iniciarmos a implementação do comportamento descrito.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    import turtle
     
    def drawLsystem(aTurtle,instructions,angle,distance):
        savedInfoList = []
        for cmd in instructions:
            if cmd == 'F':
                aTurtle.forward(distance)
            elif cmd == 'B':
                aTurtle.backward(distance)
            elif cmd == '+':
                aTurtle.right(angle)
            elif cmd == '-':
                aTurtle.left(angle)
            elif cmd == '[':
                savedInfoList.append([aTurtle.heading(),aTurtle.xcor(),aTurtle.ycor()])
                print(savedInfoList)
            elif cmd == ']':
                newInfo = savedInfoList.pop()
                print(newInfo)
                print(savedInfoList)
            else:
                print('Error:', cmd, 'is an unknown command')
     
    t = turtle.Turtle()
    inst = "FF[-F[-X]+X]+F[-X]+X"
    drawLsystem(t,inst,60,20)
     
     
    (list_lsys1)

    Quando executamos este exemplo vemos que a figura não é muito interessante, mas note que é exibido e como salvamos a informação sobre as tartarugas e acrescentada e removida do final da lista. No próximo exemplo faremos uso da informação da lista para salvar e recuperar as posições da tartaruga e o seu sentido quando necessário. Usaremos um exemplo mais longo para que você tenha uma ideia de que tipo de desenho podemos obter através de um sistema-L.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    import turtle
     
    def drawLsystem(aTurtle,instructions,angle,distance):
        savedInfoList = []
        for cmd in instructions:
            if cmd == 'F':
                aTurtle.forward(distance)
            elif cmd == 'B':
                aTurtle.backward(distance)
            elif cmd == '+':
                aTurtle.right(angle)
            elif cmd == '-':
                aTurtle.left(angle)
            elif cmd == '[':
                savedInfoList.append([aTurtle.heading(),aTurtle.xcor(),aTurtle.ycor()])
                print(savedInfoList)
            elif cmd == ']':
                newInfo = savedInfoList.pop()
                aTurtle.setheading(newInfo[0])
                aTurtle.setposition(newInfo[1],newInfo[2])
            else:
                print('Error:', cmd, 'is an unknown command')
     
    t = turtle.Turtle()
    inst = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF[-FFFFFFFFFFFFFFFF[-FFFFFFFF[-FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFFFFFF[-FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFFFFFFFFFFFFFF[-FFFFFFFF[-FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFFFFFF[-FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X]+FFFF[-FF[-F[-X]+X]+F[-X]+X]+FF[-F[-X]+X]+F[-X]+X"
    t.setposition(0,-200)
    t.left(90)
    drawLsystem(t,inst,30,2)
     
     
    (list_lsys2)

    Em vez de usar o string inst fornecido aqui, use o código do capítulo String, e escreve suas próprias função applyRules para implementar o sistema-L. Este exemplo usa apenas 6 expansões. Teste com um número maior de expansões. Você também pode desejar executar com um exemplo com valores diferentes para o ângulo e a distância.
    Scratch Editor

    Append versus concatenação

    O método append acrescenta um novo item no final da lista. É possível acrescentar um item no final da lista usando o operador + de concatenação. Entretanto, precisamos ser cuidadosos.
    Considere o exemplo a seguir. A lista original contém 3 inteiros. Nós inserimos a palavra “gato” no final da lista.

    1lista_orig = [45,32,88]
    2
    3lista_orig.append("gato")
    Step 1 of 2
    line that has just executed
    next line to execute
    Frames
    Objects
    (appcon1)
    Aqui usamos append que simplesmente modifica a lista. A fim de concatenar necessitamos usar o comando de atribuição:
    lista_orig = [45, 32, 88]
    
    lista_orig = lista_orig + ["gato"]
    
    Note que a palavra “gato” necessita ser colocada em uma lista já que o operador concatenação exige duas listas para fazer o seu trabalho.

    1lista_orig = [45, 32, 88]
    2
    3lista_orig = lista_orig + ["gato"]
    Step 1 of 2
    line that has just executed
    next line to execute
    Frames
    Objects
    (appcon2)
    É importante observar que com append, a lista original é simplemente modificada. É possível ver isto observando o id de lista_orig. O id é o mesmo antes e depois de executarmos append.
    Por outro lado, com concatenação, você verá que o id da lista original não é o mesmo que o id da resultado depois do comando de atribuição. Execute um passo a passo cuidadoso de ambos os exemplos para notar a diferença. Com a concatenação um nova lista é criada.
    Teste seu entendimento
    9.15.1: O que é impresso pelo trecho de código a seguir?
    uma_lista = [4, 2, 8, 6, 5]
    uma_lista = uma_lista + 999
    print(uma_lista)
    


    Listas e o laço for

    É possível percorrermos uma lista (list traversal) iterando através de itens ou iterando através de índices.
    1
    2
    3
    4
    5
    6
    frutas = ["pera", "laranja", "banana", "cereja"]
     
    for uma_fruta in frutas:     # por item
        print(uma_fruta)
     
     
    (chp09_03a)

    É quase como leríamos em linguagem natural: para (cada) fruta) em (a lista de) frutas, escreva (o nome da) fruta.
    Podemos também usar o índice para acessar os itens iterativamente.
    1
    2
    3
    4
    5
    6
    frutas = ["pera", "laranja", "banana", "cereja"]
     
    for posicao in range(len(frutas)):     # por índice
        print(frutas[posicao])
     
     
    (chp09_03b)

    Neste exemplo, em cada iteração do laço, a variável posição é usada como um índice da lista, imprimindo o posicao-ésimo item. Note que usamos len como limite superior do intervalo de tal forma que podemos iterar corretamente independentemente do número de itens na lista.
    Qualquer expressão sequencial pode ser usada em um laço for. Por exemplo, a função range retornal uma sequência de inteiros.
    1
    2
    3
    4
    5
    for numero in range(21):
        if numero % 3 == 0:
            print(numero)
     
     
    (chp09_for3)

    Este exemplo exibe todos os multiplos de 3 entre 0 e 20.
    Como listas são mutáveis, é frequentemente desejável que modifiquemos os elementos de uma lista a medida que ela é percorrida. No código a seguir todos os números inteiros entre 1 e 5 são elevados ao quadrado utilizando iteração por posição.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    numeros = [1, 2, 3, 4, 5]
    print(numeros)
     
    for i in range(len(numeros)):
        numeros[i] = numeros[i]**2
     
    print(numeros)
     
     
    (chp09_for4)

    Para um minuto para refretir sobre range(len(numeros) até que você entenda como funciona. Estamos interessados aqui sobre ambos o valor e o índice de uma posição da lista de tal maneira que atribuir un novo valor à posição.
    Scratch Editor

    Teste seu entendimento
    9.16.1: O que é impresso pelo trecho de código a seguir?
    lista = [4, 2, 8, 6, 5]
    nova_lista = [ ]
    for item in lista:
       nova_lista.append(item+5)
    print(nova_lista)
    




    Listas como parâmetros

    Funções que recebem listas como argumentos e as alteram durante a execução são chamadas de modificadoras (modifiers) e as mudanças elas realizam são chamadas efeitos colaterais (side effects). Ao passar uma lista como argumento estamos realmente passando para a função uma referência para a lista e não um cópia (clone) da lista. Como listas são mutáveis as alterações feitas nos elementos referenciados pelos parâmetros mudarão a lista que o argumento está referenciando. Por exemplo, a função a seguir recebe uma lista como argumento e multiplica cada elemento da lista por 2:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def double_stuff(lista):
        """ (list) -> None
        Recebe uma lista referenciada por
        'lista' e sobreescreve cada
        elemento da lista com o dobro do
        seu valor.
        """
        for posicao in range(len(lista)):
            lista[posicao] = 2 * lista[posicao]
     
    things = [2, 5, 9]
    print(things)
    double_stuff(things)
    print(things)
     
     
    (chp09_parm1)

    O parâmetro lista e a variável (argumento) things são apelidos para o mesmo objeto.
    State snapshot for multiple references to a list as a parameter Como a lista de objetos é compartilhada por duas referências, existe apenas uma cópia. Se a função modifica os elementos da lista parâmetros, o função que fez a chamada também enxerga as alterações, já que as alterações estão ocorrendo no original.
    This can be easily seen in codelens. Note that after the call to double_stuff, the id of the formal parameter uma_lista is the same as the id of things.

    1def double_stuff(lista):
    2    """ (list) -> None
    3    Recebe uma lista referenciada por
    4    'lista' e sobreescreve cada elemento
    5    da lista com o dobro do seu valor.
    6    """
    7    for posicao in range(len(lista)):
    8        lista[posicao] = 2 * lista[posicao]
    9
    10things = [2, 5, 9]
    11
    12double_stuff(things)
    Step 1 of 11
    line that has just executed
    next line to execute
    Frames
    Objects
    (chp09_parm1_trace)

    Função pura

    Uma função pura (pure function) não produz efeito colateral. Sua comunicação com a função que a chamou é somente através do parâmetros, que não são modificados e um valor é retornado. Aqui está um versão pura da função double_stuff da seção anterior. Para usar versão pura de double_stuff e modificar things, devemos atribuir o valor retornado a things :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    def double_stuff(lista):
        """ (list) -> list
        Recebe uma lista referenciada por
        'lista' e cria e retorna uma nova
        lista em que cada elemento e' o
        dobro do valor correspondente
        na lista original.
        """
        nova_lista = []
        for valor in lista:
           novo_elemento = 2 * valor
           nova_lista.append(novo_elemento)
        return nova_lista
     
    things = [2, 5, 9]
    print(things)
    things = double_stuff(things)
    print(things)
     
     
    (ch09_mod2)

    Mais uma vez, codelens nos ajuda a ver as referências e os objetos passados como parâmetros e retornados.

    1def double_stuff(lista):
    2    """ (list) -> list
    3    Recebe uma lista referenciada por
    4    'lista' e cria e retorna uma nova
    5    lista em que cada elemento e' o
    6    dobro do valor correspondente
    7    na lista original.
    8    """
    9    nova_lista = []
    10    for valor in lista:
    11       novo_elemento = 2 * valor
    12       nova_lista.append(novo_elemento)
    13    return nova_lista
    14
    15things = [2, 5, 9]
    16things = double_stuff(things)
    Step 1 of 16
    line that has just executed
    next line to execute
    Frames
    Objects
    (ch09_mod3)
    Scratch Editor

    Qual é melhor?

    Tudo que é feito com uma função modificadora pode também ser realizado com uma função pura. De fato, algumas linguagens de programação somente permitem funções puras. Existe alguma evidência que programas que usam funções puras são desenvolvidos mais rapidamente e propagam menos erros que programas que usam funções modificadoras. No entanto, modificadoras são as vezes convenientes e em alguns casos, programas funcionais não menos eficientes.
    Em geral, recomendamos que você escreva funções puras sempre que for razoável fazer isso é apele para modificadoras somente se existe uma boa vantagem em fazer isso. Este método pode ser chamado de estilo funcional de programação (functional programming style).

    Funções que produzem listas

    A versão pura da função double_stuff acima faz uso de um padrão (pattern) que você deve guardar na sua caixa de ferramentas. Sempre que você necessitar escrever uma função que cria e retorna uma lista, o padrão usualmente é:
    inicialize uma variável para a lista nova com a lista vazia
    itere
        crie um novo elemento
        append esse novo elemento a lista nova
    retorne a lista nova
    
    Vejamos outro uso desse padrão. Suponha que tenhamos uma função primo(x) que recebe um número inteiro x e retorna True se o valor de x é primo e False em caso contrário. Agora, escrevemos uma função que recebe um número inteiro n e cria e retorna uma lista com todos os números primos menores que n:
    def primos_ate(n):
        """ (int) -> list
        Recebe um inteiro n e cria e retorna a lista dos números
        primos menores que n.
        """
        lista_primos = []
        for i in range(2,n):
            if primo(i):
                lista_primos.append(i);
    
        return lista_primos
    

    List comprehensions

    No exemplo anterior criamos uma lista de uma sequência de valores (os inteiros entre 2 e n) baseados em um critério de seleção (ser primo). Um maneira simples para realizar em Python esse tipo de processamento é o uso de list comprehension. (N.d.T. também traduzido para o português como abrangência de listas. Ver o comentário em: List comprehensions ou abrangências de listas.)
    List comprehension é uma maneira compacta de criar listas. A forma geral para obter esse efeito é:
    [<expressão> for <item> in <sequência> if <condição>]
    
    onde a cláusula if é opcional. Por exemplo,
    1
    2
    3
    4
    5
    6
    7
    minha_lista = [1, 2, 3, 4, 5]
     
    sua_lista = [item ** 2 for item in minha_lista]
     
    print(sua_lista)
     
     
    (list)

    A expressão descreve cada elemento da lista que está sendo criada. A cláusula for itera sobre cada elemento da sequencia. Os itens são filtrados pela cláusula if se existe alguma. No exemplo acima, o comando for``faz com que a variável ``item assuma todos os valores na lista minha_lista. Cada item é elevado ao quadrado antes de ser inserido na lista que está sendo construída. O resultados é a lista dos quadrados dos valores em minha_lista.
    Para escrever a função primos_ate usaremos a função primos como um filtro dos inteiros na sequência resultante de range. Em outras palavras, para cada inteiro de 2 até n, exclusive n, se o inteiro é primo, ele será mantido na lista resultante.
    def primes_ate(n):
        """ (int) -> list
        Recebe um inteiro n e cria e retorna a lista dos números
        primos menores que n usando 'list comprehension'.
        """
        lista_primos = [num for num in range(2,n) if primo(num)]
        return lista_primos
    
    Scratch Editor

    Teste seu entendimento
    9.20.1: O que é impresso pelo trecho de código a seguir?
    uma_lista = [4,2,8,6,5]
    outra_lista = [num*2 for num in uma_lista if num%2==1]
    print(outra_lista)
    




    Listas aninhadas

    Uma lista aninhada (nested list) é uma lista que aparece como um elemento em uma outra lista. Nessa lista, o elemento com índice 3 é uma lista aninhada. Se executarmos print(lista[3]), obteremos [10, 20]. Para acessar um elemento de uma lista aninhada podemos proceder em dois passos. Primeiro, acessamos a lista aninhada, depois acessamos o item de interesse. Também é possível combinar esses passos usando o operador colchetes que são aplicados da esquerda para a direita.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    lista = ["oi", 2.0, 5, [10, 20]]
    lista_aninhada = lista[3]
    print(lista_aninhada)
    item = lista_aninhada[1]
    print(item)
     
    print(lista[3][1])
     
     
    (chp09_nest)

    Teste seu entendimento
    9.21.1: O que é impresso pelo trecho de código a seguir?
    lista = [ [4, [True, False], 6, 8], [888, 999] ]
    if lista[0][1][0]:
       print(lista[1][0])
    else:
       print(lista[1][1])
    




    Strings e listas

    Dois dos métodos mais úteis que operam sobre strings envolvem listas de strings. O método split quebra um string em uma lista de palavras. Por palavra entenda-se um string limitado por um conjunto de caracteres pré-definidos. Em caso de omissão (default), qualquer número de caracteres brancos (whitespace characters) é considerado como limite de uma palavra.
    1
    2
    3
    4
    5
    musica = "Eduardo e Monica um dia se encontraram sem querer..."
    lista_palavras = musica.split()
    print(lista_palavras)
     
     
    (ch09_split1)

    Um argumento opcional chamado de delimitador (delimiter) pode ser usado para especificar quais caracteres serão usados como fronteira de palavras. No exemplo a seguir usamos o string “se”
    1
    2
    3
    4
    5
    musica = "Eduardo e Monica um dia se encontraram sem querer..."
    lista_palavras = musica.split("se")
    print(lista_palavras)
     
     
    (ch09_split2)

    Note que o delimitador não aparece no resultado.
    O método join faz o trabalho inverso do método split. Determinamos um string separador (separator), frequentemente chamado de cola (glue) e juntamos os elementos na lista utilizando a cola entre cada par de elemento.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    lista = ["vermelho", "azul", "verde"]
    cola = ';'
    s = cola.join(lista)
    print(s)
    print(lista)
     
    print("***".join(lista))
    print("".join(lista))
     
     
    (ch09_join)

    A lista que estamos grudando (lista no exemplo) não é modificada. É possível utilizar qualquer string como cola, inclusive o string vazio.
    Scratch Editor

    Teste seu entendimento
    9.22.1: O que é impresso pelo trecho de código a seguir?
    escritora = "Carolina Maria de Jesus"
    lista_de_nomes = escritora.split()
    inic = ""
    for nome in lista_de_nomes:
       inic = inic + nome[0]
    print(inic)
    




    Função de conversão list

    Python possui uma função nativa chamada list que procura converter o seu argumento para o tipo list.
    1
    2
    3
    4
    xs = list("Crunchy Frog")
    print(xs)
     
     
    (ch09_list1)

    O string “Crunchy Frog” é transformado em uma lista que contem cada caractere do string. Em geral, qualquer sequência pode ser convertida em uma lista usando esta função. O resultado sera a lista contendo os elementos na sequência original. Não é válido usar a função list sobre qualquer argumento que não seja uma sequência.
    É importante observar que a função de conversão list colocará cada elemento da sequência original em uma nova lista. Quando estamos trabalhando com strings isto é muito diferente do resultado do método split. Enquanto que split quebra uma string em um lista de “palavras”, list sempre quebra o string em uma lista de caracteres.

    Tuplas e mutabilidade

    Até agora vimos dois tipos de coleções sequenciais de objetos: strings, que são compostos de caracteres; e listas. que são formados por elementos de um qualquer tipo. Uma das diferenças que notados é que os elementos de uma lista podem ser modificados, mas os caracteres de um string não podem. Em outras palavras, strings são imutáveis (immutable) e listas são mutáveis (mutable).
    Uma tupla (tuple), como uma lista, é um sequência de items de qualquer tipo. Entretanto, diferentemente de listas, tuples são imutáveis. Sintaticamente, uma tupla é uma sequência de valores separadas por uma vírgula. Apesar de não ser necessário, há a convenção de se envolver uma tupla entre parêntese:
    fernanda = ("Fernanda", "Montenegro", 1929, "Central do Brasil", 1998, "Atriz", "Rio de Janeiro, RJ")
    
    Tuplas são úteis para representarmos o que em outras linguagens frequentemente chamamos de registros (records) — alguma informação relacionada, como o seu histórico escolar, Não há descrição do que cada um desses campos (fields) significam, mas podemos ter um palpite. Uma tupla nos permite agruparmos informações relacionadas e usá-la como um único objeto.
    Tuplas admitem a mesma sequência de operações que strings e listas. Por exemplo, com o operador de indexação selecionamos um elemento de uma tupla.
    Como strings, se tentarmos utilizar o operador de atribuição para modificarmos um elemento da tupla, obteremos um erro.
    fernanda[0] = 'X'
    TypeError: 'tuple' object does not support item assignment
    
    É claro que, mesmo que não seja possível modificarmos os elementos de uma tupla, nós podemos fazer com que uma variável faça referência a uma nova tupla que armazena indormações diferentes. Para construirmos uma nova tupla é conveniente que utilizemos fatiamento para selecionar as partes da tupla original e juntemos com outras informações a fim de obtermos uma nova tupla. Assim, fernanda tem um filme mais recente e nós podemos desejar alterar a sua tupla. Podemos facilmente usar fatiar as partes da tupla original que desejamos concatenar a fim de obtermos uma nova tupla.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    fernanda = ("Fernanda", "Montenegro", 1929, "Central do Brasil", 1998, "Atriz", "Rio de Janeiro, RJ")
    print(fernanda[2])
    print(fernanda[2:6])
     
    print(len(fernanda))
     
    fernanda = fernanda[:3] + ("Boa Sorte", 2014) + fernanda[5:]
    print(fernanda)
     
     
    (ch09_tuple1)

    Para criar uma tupla com um único elemento (mas você provavelmente não fará isso frequentemente), podemos incluir no final uma vírgula, já que sem a vírgula no final, Python tratará (5) abaixo como um número inteiro entre parenteses:
    1
    2
    3
    4
    5
    6
    7
    tup = (5,)
    print(type(tup))
     
    x = (5)
    print(type(x))
     
     
    (chp09_tuple2)

    Atribuição de tuplas

    Python tem um mecanismo muito poderoso de atribuição de tuplas (tuple assignment) que permite uma tupla de variáveis na esquerda receber valore de uma tupla de variáveis a direita do operador = de atribuição.
    (nome, sobrenome, ano_de_nascimento, filme, ano_do_filme, profissao, local_de_nascimento) = fernanda
    
    Isso é equivalente a sete comandos de atribuição, tudo em um linha e de maneira simples. Um requisito é que o número de variáveis a esquerda deve ser o mesmo que o número de valores na tupla.
    Frequentemente, é útil trocarmos os valores de duas variáveis. Com o comando de atribuição convencional necessitamos de uma variável temporária. Por exemplo, para trocar os valores de a e b:
    temp = a
    a = b
    b = temp
    
    Atribuição entre tuplas faz o mesmo serviço de uma maneira muito elegante:
    (a, b) = (b, a)
    
    Naturalmente, o número de variáveis a esquerda e o número de valores a direita devem ser o mesmo.
    >>> (a, b, c, d) = (1, 2, 3)
    ValueError: need more than 3 values to unpack
    

    Tuplas como valor de retorno

    Funções podem retornar tuplas como valor de retorno. Isto é muito conveniente — frequentemente desejamos saber qual foi o maior número de gols marcados e o maior número de gols sofridos por um time, ou desejamos o média e desvio padrão de um conjunto de dados, ou sejamos saber um dia, mês e ano ou se estamos fazendo alguma modelagem ecológica desejamos saber o número de coelho e lobos em uma ilha em um certo momento. Em cada um desses casos, uma função (que só pode retornar um único valor), pode cria uma tupla formada por vários valores.
    Por exemplo, podemos escrever uma função que retorna a área de um círculo e comprimento de uma circunferência de um dado raio.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def circInfo(r):
        """ (numero) -> (float,float)
        Recebe um numero r e retorna o comprimento da circunferencia
        de raio r e a area do circulo de raio r.
        """
        c = 2 * 3.14159 * r
        a = 3.14159 * r * r
        return (c, a)
     
    print(circInfo(10))
     
     
    (chp09_tuple3)

    Scratch Editor

    Glossário

    apelidos (aliases)
    Várias variáveis fazendo referência a um mesmo objeto.
    clonar (clone)
    Criar um novo objeto com os mesmo valores de um objeto existente. Copiar uma referência de um objeto cria um apelido mas não cria um clone do objeto.
    delimitador (delimiter)
    Um caractere ou string usado para indicar onde um string deve ser “quebrado”.
    efeito colateral (side effect)
    Um mudança no estado de um programa feito por uma função que foi invocada que não é o resultado do valor retornado pela função. Efeitos colaterais só podem ser produzidos por função midificadoras.
    elemento
    Um dos valores em uma lista (ou outra sequência). O operador colchetes seleciona elementos de uma lista.
    função pura (pure functon)
    Uma função que não produz efeitos colaterais. Funções puras apenas alteram os estado (variáveis) das funções que a chamam através de valores de retorno.
    índice (index)
    Uma variável, valor ou expressão do tipo int que indica um elemento de uma lista, string ou tupla.
    lista (list)
    Uma coleção de objetos, onde cada objeto é identificado por um índice. Como outros tipos str, int, float, etc. existe também a função list que procura converter o seu argumento para uma lista.
    lista aninhada (nested list)
    Uma lista que é um elemento de uma outra lista.
    modificadora (modifier)
    Uma função que altera os seus argumntos. Somente argumentos de tipos mutáveis podem ser alterados por funções modificadoras.
    objeto (object)
    Um valor a que uma variável pode se referir.
    percorrer um lista (list traversal)
    Acesso sequencial a cada elemneto em uma lista.
    padrão (pattern)
    Uma sequência de comandos ou um estilo de escrever código que é potencialmente aplicável em várias situações. Parte de se tornar um cientista da computação madura está em aprender e estabelecer padrões e algoritmos que formam a sua caixa de ferramentas. Padrões frequentemente correspondem ao seu “mental chunking”.
    sequência (sequence)
    Qualquer tipo de dados que consiste de uma coleção ordenada de elementos, com cada elemento identificado por um índice.
    tipo de dado mutável (mutable data type)
    Um tipo de dado em que seu elementos podem ser modificados. Todos os tipos mutáveis são compostos por outros tipos. Listas são mutáveis; strings e tuplas não são mutáveis.

    Exercícios

    1. Desenhe um diagrama de referências para a e b antes e depois de ser executada a terceira linha do seguinte trecho de código:
      a = [1, 2, 3]
      b = a[:]
      b[0] = 5
      
    2. Cria uma lista chamada minha_lista com os seguinte items: 76, 92.3, “oi”, True, 4, 76.

  2. Escreva comandos para:
    1. Inserir “pera” e 76 no final da lista.
    2. Inserir o valor “gato” na posição de índice 3.
    3. Inserir o valor 99 no início da lista.
    4. Encontrar o índice de “oi”.
    5. Contar o número de ocorrências de 76 na lista.
    6. Remover a primeira ocorrência de 76 da lista.
    7. Remover True True da lista usando pop e index.

  3. Crie uma lista contendo 100 números inteiros aleatórios entre 0 e 1000 (usando iteração, ´´append´´ e o módulo random). Escreva uma função media que recebe uma lista de números como parâmetros e retorna a média dos valores na lista.

  4. Escreva uma função que recebe a lista de inteiros do exercício anterior e retorna o maior valor na lista. (Observação: existe uma a função nativa max que faz o serviço, mas você não deve usá-la.)

  5. Escreva uma função soma_de_quadrados(xs) que recebe uma lista de números xs e retorna a soma dos quadrados dos números na lista. Por exemplo soma_dos_quadrados([2, 3, 4]) deve retorna 4+9+16 que é 29.

  6. Escreva uma função que recebe uma lista de números inteiros e retorna a quantida de números ímpares na lista.

  7. Escreva uma função que recebe uma lista de números inteiros e retorna a soma dos números pares na lista.

  8. Escreva uma função que recebe uma lista de números e retorna a soma dos números negativos na lista.

  9. Escreva uma função que recebe uma lista de palavras (strings) e retorna o número de palavras na lista que tem comprimento 5.

  10. Escreva uma função que recebe uma lista de números inteiros e retorna a soma dos números na lista exclusive o primeiro número par.

  11. Escreva uma função que recebe uma lista de palavras (strings) e retorna o número de palavras que ocorre na lista até e inclusive a primeira ocorrência da palavra “sam”.

  12. Apesar de Python nós fornecer uma grande lista de métodos nativos é uma boa prática e instrutivo pensar sobre como elas podem ser implementadas. Implemente uma função que se comporte como:
    1. count
    2. in
    3. reverse
    4. index
    5. insert

  13. Escreva uma função troca(s, velho, novo) que recebe os strings s, velho e novo e troca em s todas as ocorrências de velho por novo:
    test(troca('Mississippi', 'i', 'I'), 'MIssIssIppI')
    
    s = 'I love spom!  Spom is my favorite food.  Spom, spom, spom, yum!'
    test(troca(s, 'om', 'am'),
           'I love spam!  Spam is my favorite food.  Spam, spam, spam, yum!')
    
    test(troca(s, 'o', 'a'),
           'I lave spam!  Spam is my favarite faad.  Spam, spam, spam, yum!')
    
    Dica: use os métodos split e join.

  14. Aqui estão as regras para um sistema-L que cria algo que lembra um jardim comum de evas. Implemente as regras a seguir e teste-as. Use o ângulo de 25.7 graus.:
    H
    H --> HFX[+H][-H]
    X --> X[-FFF][+FFF]FX
    

  15. Aqui está outro sistema-L. Use o ângulo de 25 graus:
    F
    F --> F[-F]F[+F]F