Professional Documents
Culture Documents
Programaci n en Python o
Curso de actualizaci n docente o Facultad de Ciencias
David P. Sanders
22 de junio de 2010
Captulo 1
Qu es Python? e
Python es un lenguaje de programaci n que surgi en 1990. Desde entonces se ha desarrollado enormemente, o o para volverse un lenguaje de programaci n moderno, y uno de los m s utilizados en el mundo. o a Python es un lenguaje interpretado no es necesario compilar constantemente cada programa, si no se puede utilizar de manera interactiva. Por lo tanto, es una herramienta id nea para llevar a cabo tareas de c mputo o o cientco, tales como an lisis de datos, gracaci n de resultados, y exploraci n de problemas. En este sentido, a o o se puede comparar con programas comerciales tales como Matlab. Tambi n hay paquetes que permiten llevar a e cabo c lculos simb licos a trav s de Python, de los cuales destaca sage (www.sagemath.org), por lo cual a o e tambi n se puede considerar como competidor de Mathematica y Maple. e Python viene con una losofa de bateras incluidas. Esto quiere decir que hay muchas bibliotecas disponibles que est n dise adas para facilitarnos la vida al hacer diferentes tareas, desde el c mputo cientco hasta la a n o manipulaci n de p ginas web. Por lo tanto, Python es un lenguaje sumamente vers til. o a a Cabe enfatizar que se suele encontrar Python f cil de aprenderse y de utilizarse. Por lo tanto, considero que a Python es tambi n el lenguaje id neo para la ense anza del c mputo cientco en la Facultad de Ciencias, un e o n o campo que se ha vuelto de suma importancia.
1.1.
La meta principal de este curso es la de ense ar las t cnicas b sicas de Python en el contexto del c mputo n e a o cientco, y en particular de la fsica computacional, con un n de actualizaci n docente en la Facultad de o Ciencias.
Captulo 2
2.1.
El entorno ipython
El entorno principal que ocuparemos para trabajar de manera interactiva es ipython. Otro posible es idle. ipython est dise ado para maximar la productividad al utilizar Python. En particular, tiene ciertos comandos a n que no existen en otros interpretadores de Python. Uno muy util es
In [1]: logstart primero_log.py
Este comando graba un log (bit cora) de todo lo que se teclea en la sesi n actual en el archivo dado, aqui a o
primero_log.py.
Otra funci n de suma utilidad en ipython es que la de completar palabras parciales con la tecla <TAB>. o Adem s, los comandos who y whos proveen informaci n de las funciones nuevas agregadas en la sesi n. a o o La documentaci n para cualquier funci n o comando est disponible en ipython al poner ?, por ejemplo o o a
who?
2.2.
Aritm tica e
Aqu, ** indica una potencia, como en Fortran, y las par ntesis alteran la prioridad en las operaciones. e Es necesario1 tener cuidado al hacer manipulaciones con enteros:
1 / 2
1 En
4
3 / 2 5 / 2
ya que el resultado se redondea al entero m s cercano. Para evitar eso, basta un punto decimal: a
1 / 2.
Los n meros sin punto decimal se consideran enteros, y los con punto decimal otantes (de doble precisi n). u o Los enteros pueden ser arbitrariamente grandes:
2 ** 2 ** 2 ** 2 ** 2
2.3.
Variables
Para llevar a cabo c lculos, necesitamos variables. Las variables se declaran como debe de ser: a
a = 3 b = 17.5 c = 1 + 3j print a + b / c
Python reconece de manera autom tica el tipo de la variable seg n su forma. El comando print imprime su a u argumento de una manera bonita. Al reasignar una variable, se pierde la informaci n de su valor interior, incluyendo el tipo: o
a = 3 a = -5.5
2.4.
2.5.
Listas
La estructura de datos principal en Python es la lista. Consiste literalmente en una lista ordenada de cosas, y reemplaza a los arreglos en otros lenguajes. La diferencia es que las listas en Python son autom ticamente de a longitud variable, y pueden contener objetos de cualquier tipo. Una lista se dene con corchetes ([ y \):
l = [3, 4, 6]
Por lo tanto, es una estructura de datos muy sencillo. Los elementos de la lista se pueden extraer y cambiar usando la notaci n l[i], donde i indica el n mero del o u elemento, empezando desde 0:
l = [1, 2, 3] print l[0], l[1] l[0] = 5 l
Como siempre, las otras operaciones que se pueden llevar a cabo con la lista se pueden averiguar en ipython con l.<TAB>.
# error!
Las n-adas se utilizan para agrupar informaci n. Se pueden asignar como sigue: o
a, b = 3, 5 print a; print b
2.7.
Python tiene una biblioteca est ndar amplia, lo cual siempre est disponible en cualquier instalaci n de Python. a a o La documentaci n para esta biblioteca est disponible en http://docs.python.org/library/ o a Por ejemplo, la secci n 9 incluye informaci n sobre el m dulo fractions: o o o
from fractions import Fraction a = Fraction(3, 5)
6
b c d d e = Fraction(1) = a + b = Fraction(4, 6) = a + d
Cada cosa en Python es un objeto, que tiene propiedades y operaciones disponibles. Fraction es un tipo de objeto (clase); sus operaciones est n disponibles en ipython a trav s de Fraction.<TAB>. Las que empiezan a e con __ son internos y deberan de ignorarse por el momento; las dem s son accesibles al usuario. a
2.8.
Una vez que las secuencias de comandos se complican, es util poder guardarlos en un programa, o script. Eso consiste en un archivo de texto, cuyo nombre termina en .py, donde se guarda la secuencia de comandos. Por ejemplo, guardemos el c digo anterior en el archivo cuad.py Podemos correr el c digo desde ipython o o con
run cuad
Al terminar de correr el programa, el control regresa a ipython, pero todava tenemos acceso a las variables y funciones denidas en el script. Alternativamente, podemos tratar el script como un programa en s al ejecutar desde el shell
python cuad.py
Al terminar, el control regresa al shell, y perdemos la informaci n adentro del script. o De hecho, un script se puede considerar un m dulo en s, que tambi n se puede importar: o e
from cuad import *
Captulo 3
Estructuras de control
Por estructuras de control, se entiende los comandos tales como condicionales, bucles, y funciones, que cambian el orden de ejecuci n de un programa. o Las estructuras de control tienen un formato en com n. A diferencia de C++ y Fortran, no existen instrucciones u que indiquen donde empieza y termina un bloque del programa: en Python, un bloque empieza por :, y su extensi n se indica por el uso de una cantidad denida de espacio en blanco al principio de cada lnea. Un buen o editor de texto te permite hacer eso de manera autom tica. a
3.1.
Condicionales
Para checar una condici n y ejecutar c digo dependiente del resultado, se ocupa if: o o
a = raw_input('Dame el valor de a') if a > 0: print "a es positiva" a = a + 1 elif a == 0: # NB: dos veces = print "a es 0" else: print "a es negativa"
En el primer caso, hay dos comandos en el bloque que se ejecutar en el caso de que a > 0. N tese que elif a o es una abreviaci n de else:if o Las condiciones que se pueden ocupar incluyen: <, <= y != (no es igual). Para combinar condiciones se ocupan las palabras and y or:
a = 3; b=7 if a>1 and b>2: print "Grandes" if a>0 or b>0: print "Al menos uno positivo"
3.2.
Bucles
La parte central de muchos c lculos cientcos consiste en llevar a cabo bucles, aunque en Python, como a veremos, eso se desenfatiza. 7
3.2.1.
El tipo de bucle m s sencillo es un while, que ejecuta un bloque de c digo mientras una cierta condici n se a o o satisfaga, y suele ocuparse para llevar a cabo una iteraci n en la cual no se conoce de antemano el n mero de o u iteraciones necesario. El ejemplo m s sencillo de un while, donde s se conoce la condici n terminal, para contar hasta 9, se puede a o hacer como sigue:
i = 0 while i < 10: i += 1 print i
# equivalente a i = i + 1
N tese que si la condici n deseada es del tipo hasta. . . , entonces se tiene que utilizar un while con la o o condici n opuesta. o Ejercicio: Encuentra los n meros de Fibonacci menores que 1000. u Ejercicio: Implementa el llamado m todo babil nico para calcular la raz cuadrada de un n mero dado y. Este e o u m todo consiste en la iteraci n xn+1 = 1 [xn + (y/xn )]. Qu tan r pido converge? e o e a 2
3.2.2.
for
Un bucle de tipo for se suele ocupar para llevar a cabo un n mero de iteraciones que se conoce de antemano. u En el bucle de tipo for, encontramos una diferencia importante con respecto a lenguajes m s tradicionales: a podemos iterar sobre cualquier lista y ejecutar un bloque de c digo para cada elemento de la lista: o
l = [1, 2.5, -3.71, "hola", [2, 3]] for i in l: print 2*l
Si queremos iterar sobre muchos elementos, es m s util construir la lista. Por ejemplo, para hacer una iteraci n a o para todos los n meros hasta 100, podemos utilizar u
for i in range(100): print 2*i
Qu es lo que hace la funci n range? Para averiguarlo, lo investigamos de manera interactiva con ipython: e o
range(10) range(3, 10, 2)
N tese que range no acepta argumentos de punto otante. o Ejercicio: Toma una lista, y crea una nueva que contiene la duplicaci n de cada elemento de la lista anterior. o
3.3.
Funciones
Las funciones se pueden considerar como subprogramas que ejecutan una tarea dada. Corresponden a las subrutinas en Fortran. En Python, las funciones pueden o no aceptar argumentos, y pueden o no regresar resultados. La sintaxis para declarar una funci n es como sigue: o
def f(x): print "Argumento x = ", x return x*x
y se llama as:
Las funciones se pueden utilizar con argumentos de cualquier tipo el tipo de los argumentos nunca se especica. Si las operaciones llevadas a cabo no se permiten para el tipo que se provee, entonces Python regresa un error:
f("hola")
Se puede proporcionar una forma sencilla de documentaci n de una funci n al proporcionar un docstring: o o
def cuad(x): """Funcion para llevar un numero al cuadrado. Funciona siempre y cuando el tipo de x permite multiplicacion. """ return x*x
nos da esta informaci n. Si la funci n est denida en un archivo, entonces cuad?? muestra el c digo de la o o a o denici n de la funci n. o o Ejercicio: Pon el c digo para calcular la raz cuadrada de un n mero adentro de una funci n. Calcula la raz o u o de los n meros de 0 hasta 10 en pasos de 0.2 e imprimir los resultados. u
3.4.
Para llevar a cabo c lculos con funciones m s avanzadas, es necesario importar la biblioteca est ndar de maa a a tem ticas: a
from math import *
Eso no es necesario al correr ipython -pylab, que invoca un modo especco de ipython1 . Sin embargo, eso importa mucho m s que la simple biblioteca de matem ticas. N tese que Python est escrito en C, as que a a o a la biblioteca math provee acceso a las funciones matem ticas que est n en la biblioteca est ndar de C. M s a a a a adelante veremos como acceder a otras funciones, tales como funciones especiales. Ejercicio: Cu l es la respuesta de la entrada sqrt(-1)? a Ejercicio: Intenta resolver la ecuaci n cuadr tica ax2 + bx + c = 0 para distintos valores de a, b y c. o a Para permitir operaciones con n meros complejos como posibles respuestas, se ocupa la biblioteca (m dulo) u o cmath. Si hacemos
from cmath import *
10
Sin embargo, ya se perdieron las funciones anteriores, es decir, las nuevas funciones han reemplazado a las distintas funciones con los mismos nombres que haba antes. Una soluci n es importar la biblioteca de otra manera: o
import cmath
Ahora las funciones que se han importado de cmath tienen nombres que empiezan por cmath.:
cmath.sqrt(-1) ipython ahora nos proporciona la lista de funciones adentro del m dulo si hacemos cmath.<TAB>. o
Captulo 4
4.1.
La manera m s f cil de entender c mo utilizarlo es por ejemplo. a a o Empecemos creando una esfera:
s = sphere()
Podemos ver sphere() como una funci n que llamamos para crear un objeto tipo esfera. Para poder manipular o este objeto despu s, se lo asignamos el nombre s. e Al crear objetos en Visual Python, se despliegan por autom tico, y en 3 dimensiones! Como se puede imaginar, a hay una cantidad feroz de trabajo abajo que permite que funcione eso, pero afortunadamente no tenemos que preocuparnos por eso, y simplemente podemos aprovechar su existencia. Qu podemos hacer con la esfera s? Como siempre, ipython nos permite averiguarlo al poner s.<TAB>. e B sicamente, podemos cambiar sus propiedades internas, tales como su color, su radio y su posici n: a o
s.color = color.red s.radius = 0.5 s.pos = 1, 0, 0 # o s.color = 1, 0, 0
Aqu, s.pos es un vector, tambi n denido por Visual, como podemos ver al teclear type(s.pos). Los e vectores en Visual son diferentes de los que provee numpy. Los de Visual siempre tienen 3 componentes. Ahora podemos construir otros objetos, incluyendo a box, cylinder, etc. N tese que la gr ca se puede rotar o a en 3 dimensiones con el rat n, al arrastar con el bot n de derecho puesto, y se puede hacer un acercamiento o o con el bot n central. o
4.2.
Animaciones
Ahora llega lo bueno. C mo podemos hacer una animaci n? Una animaci n no es m s que una secuencia de o o o a im genes, desplegadas r pidamente una tras otra. As que eso es lo que tenemos que hacer: a a 11
12
s = sphere() b = box() for i in range(10000): rate(100) s.pos = i/1000., 0, 0
4.3.
Supongamos que queremos pensar en nuestra esfera como una pelota. Entonces la pelota tendr no solamente a una posici n, sino tambi n una velocidad. Se lo podemos crear as: o e
pelota = sphere() pelota.vel = vector(1,0,0)
N tese que se tiene que poner explcitamente vector, ya que sino sera una n-ada (tupla). Ahora qued denida o o la velocidad de la pelota como otra propiedad interna. Eso es b sicamente todo lo que hay que saber de Visual Python. Tambi n es posible interactuar con el teclado, a e extraer las coordenadas del rat n, etc. o
Captulo 5
5.1.
Redirecci n de la salida o
En Linux, la manera m s f cil (pero no muy exible) de guardar datos en un archivo es utilizando la llamada a a redirecci n que provee el shell (Bash). Al correr un programa as desde Bash: o ./programa > salida.dat la salida est ndar (lo que aparece en la pantalla al correr el programa) se manda al archivo especicado. As que a
python prog.py > salida.dat
mandar la salida del programa de python prog.py al archivo salida.dat. a Ejercicio: Guarda los resultados de las raices cuadradas de diferentes n meros, y grafcalos con gnuplot: u plot "salida.dat" Ejercicio: Haz una gr ca de la velocidad de convergencia del m todo Babil nico para calcular la raz cuadraa e o da.
5.2.
Leer archivos
Para leer un archivo, primero es necesario abrirlo para leerse. Supongamos que tenemos un archivo llamado datos.dat, entonces lo podemos abrir para su lectura con
entrada = open("datos.dat", "r")
El segundo argumento, "r", es para indicar que se va a leer (read) el archivo. El objeto entrada ahora representa el archivo. Para leer del archivo abierto, hay varias posibilidades. Podemos leer todo de un golpe con entrada.read(), leer todo por lneas con entrada.readlines(), o lnea por lnea con entrada.readline(). [N tese que o lo que se ha ledo ya no se puede leer de nuevo sin cerrar el archivo con entrada.close() y volverlo a abrir.] Por ejemplo, podemos utilizar
for linea in entrada.readlines(): print linea
14
for linea in entrada: print linea
Es decir, el archivo se comporta como una secuencia! Ahora, la lnea viene como una sola cadena, con espacios etc. Para extraer la informaci n, primero necesitamos o dividirlo en palabras:
palabras = linea.split()
Si todos los datos en realidad son n meros, entonces tenemos que procesar cada palabra, convirti ndola en un u e n mero: u
datos = [] for i in palabras: datos.append( float(i) )
Resulta que hay una manera m s f cil, de m s alto nivel, y (!) m s r pida de hacer eso: a a a a a
map(float, palabras)
Eso literalmente mapea la funci n float sobre la lista palabras. o Combinando todo, podemos escribir
entrada = open("datos.dat", "r") for linea in entrada: datos = map( float, linea.split() )
Ahora adentro del bucle podemos manipular los datos como queramos. Ejercicio: Para un archivo con dos columnas, leer los datos de cada columna en dos listas por separado.
5.3.
Escribir archivos
El m todo de redirigir la salida que vimos arriba es r pido y f cil. Sin embargo, no es de ninguna manera e a a exible, por ejemplo no podemos especicar desde nuestro programa el nombre del archivo de salida, ni escribir en dos archivos diferentes. Para hacer eso, necesitamos poder abrir un archivo para escribirse:
salida = open("resultados.dat", "w")
La parte m s complicada viene al momento de escribir en el archivo. Para hacerlo, ocupamos la funci n a o salida.write(). Sin embargo, esta funci n puede escribir solamente cadenas. Por lo tanto, si queremos o escribir n meros contenidos en variables, es necesario convertirlos primero a la forma de cadena. u Una manera de hacer eso es con la funci n str(), y concatenar distintas cadenas con +: o
a = 3 s = "El valor de a es " + str(a)
5.4.
La manera m s elegante de hacerlo es con la sustituci n de variables en cadenas1 . En una cadena ponemos una a o secuencia especial de caracteres, empezando por %, que indica que se sustituir el valor de una variable: a
1 Eso
15
El caracter despues del % indica el tipo de variable que incluir en la cadena: d corresponde a un entero, g o f a un otante, y s a otra cadena. Tambi n se puede poner un n mero entero, que es el tama o del campo, y un e u n punto decimal seguido por un n mero, que da el n mero de decimales para el caso de f. u u Finalmente ahora podemos imprimir en el archivo, por ejemplo
salida.write(" %g\t %g" % (a,b) )
16
Captulo 6
Acord monos que hay distintos tipos de n meros en Python, principalmente enteros (int) y otantes (float). e u Para convertir entre diferentes tipos, incluyendo cadenas, podemos utilizar
a = float(3) b = float('3.5')
6.2.
A veces, es necesaria poder llevar a cabo operaciones aritm ticas con n meros otantes (reales) con precisi n e u o superior a los 16 dgitos que provee el float (n mero de doble precisi n) de Python. Para hacerlo, existen u o varios proyectos que proveen bibliotecas con este n. La mayora de estas bibliotecas son interfaces a otros proyectos escritos en C++. Aqu veremos una opci n, la biblioteca mpmath, que est escrito completamente en Python. En principio eso o a lo hace m s lento, pero m s f cil de entender y modicar el c digo. a a a o Para cargar la biblioteca, hacemos
from mpmath import *
donde el n mero se expresa como cadena. u Al hacer manipulaciones con x, los c lculos se llevan a cabo en precisi n m ltiple. Por ejemplo, a o u
print x/6., x*10 print mpf('2.0')**2**2**2**2
Con mpmath, no hay lmite del exponente que se puede manejar. Tambi n est n denidas muchas funciones, e a por ejemplo sin, exp y log. Para imprimir un n mero con una precisi n dada, usamos u o 17
18
nprint(x, 20)
6.3.
La biblioteca numpy
Hasta ahora, hemos utilizado listas para guardar y manipular datos. Sin embargo, las listas no se comportan como vectores, y menos como matrices al sumarlos no se comportan de la manera adecuada, etc. El prop sito o de la biblioteca numpy es justamente el de proporcionar objetos que represantan a vectores y matrices matem ticos, con todas las bondades que traen consigo este tipo de objetos. a La biblioteca se carga con
from numpy import *
6.4.
Creando vectores
Los vectores se llaman (aunque es un poco confuso) arrays, y se pueden crear de distintas maneras. Son como listas, pero con propiedades y m todos adicionales para funcionar como objetos matem ticos. La manera m s e a a general de crear un vector es justamente convirtiendo desde una lista de n meros: u
from numpy import * a = array( [1, 2, -1, 100] )
Un vector de este tipo puede contener s lo un tipo de objetos, a diferencia de una lista normal de Python. Si o todos los n meros en la lista son enteros, entonces el tipo del arreglo tambi n lo es, como se puede comprobar u e con a.dtype. Es com n querer crear vectores de cierto tama o con todos ceros: u n
b = zeros( 10 ) print b
o todos unos:
b = ones( 10 ) print b
Tambi n hay distintas maneras de crear vectores que consisten en rangos ordenados, por ejemplo arange, que e funciona como range, con un punto inicial, un punto nal, y un paso:
a = arange(0., 10., 0.1)
Una notaci n abreviada para construir vectores es r_, que se puede pensar como una abreviaci n de vector o o rengl n: o
a = r_[1,2,10,-1.]
Este m todo se extiende para dar una manera r pida de construir rangos: e a
r_[3:7] r_[3:7:0.5] r_[3:7:10j]
Este ultimo utiliza un n mero complejo simplemente como otra notaci n, y es el equivalente de linspace(3,7,10). u o
19
6.5.
Los vectores creados de esta manera se pueden sumar, restar etc., como si fueran vectores matem ticos. Todas a las operaciones se llevan a cabo entrada por entrada:
a = array( [1., 4., 7. ]) b = array( [1., 2., -2. ]) print a+b, a-b, a*b, a/b, a**b
Ejercicio: C mo se puede crear un vector de 100 veces 3? o Las funciones m s comunes entre vectores ya est n denidas en numpy, entre las cuales se encuentran dot(a,b) a a para productos escalares de dos vectores de la mismo longitud, y cross(a,b) para el producto cruz de dos vectores de longitud 3. Adem s, cualquier funci n matem tica como sin y exp se puede aplicar directamente a un vector, y regrea o a sar un vector compuesto por esta funci n aplicada a cada entrada del vector, tipo map. a o Es m s: al denir una funci n el usuario, esta funci n normalmente tambi n se pueden aplicar directamente a a o o e un vector:
def gauss(x): return 1./ (sqrt(2.)) * exp(-x*x / 2.) gauss( r_[0:10] )
6.6.
Para extraer subpartes de un vector, la misma sintaxis funciona como para listas: se extraen componentes (entradas) individuales con
a = array([0, 1, 2, 3]) print a[0], a[2]
y subvectores con
b = a[1:3]
N tese, sin embargo, que en este caso la variable b no es una copia de esta parte de a. M s bien, es una vista o a de a, as que ahora si hacemos
b[1] = 10
entonces la entrada correspondiente de a tambi n cambia! Este fen meno tambi n funciona con listas: e o e
l=[1,2,3]; k=l; k[1] = 10
En general, en Python las variables son nombres de objetos; al poner b = a, tenemos un mismo objeto con dos nombres!
6.7.
Matrices
20
o con
M.reshape( 2, 2 )
nos regresa la primera componente de M, que es justamente un vector, viz. el primer rengl n de M. Si queremos o cierta entrada de la matriz, entonces m s bien necesitamos especicar dos coordenadas: a
M[0][1] M[0, 1]
[Tambi n podemos poner M.item(1) que aparentemente es ma eciente.] e s Para extraer ciertas renglones o columnas de M, utilizamos una extensi n de la notaci n para vectores: o o
M = identity(10) M[3:5] M[:, 3:5] M[3:9, 3:5] # matriz identidad de 10x10
Otros m todos utiles son diagonal, que regresa una diagonal de un arreglo: e
diagonal(M) diagonal(M, 1)
y diag, que construye una matriz con el vector dado como diagonal:
diag([1,2,3]) diag([1,2,3], 2)
21
Ejercicio: Utiliza el m todo de potencias para calcular el vector propio de una matriz cuadrada M correspone diente al valor propio de mayor m dulo. Este m todo consiste en considerar la iteraci n M n v. o e o Para algebra lineal, se ocupa el m dulo linalg: o
from numpy import linalg
Entonces las funciones del m dulo se llaman e.g. norm para la norma de un vector se llama o
linalg.norm(v)
entonces ya no se pone linalg., y se puede referir simplemente a norm. Algunas de las funciones utiles incluyen linalg.eig para calcular los valores y vectores propios de una matrix:
linalg.eig(M)
y linalg.eigvals para solamente los valores propios. Hay versiones especiales eigh y eigvalsh para matrices hermitianas o sim tricas reales. e Tambi n hay det para determinante, e inv para la inversa de una matriz. Finalmente, se puede resolver un e sistema de ecuaciones lineales M x = b con
linalg.solve(M, b)
6.9.
Hay varias funciones que regresan informaci n resumida sobre vectores y matrices, por ejemplo o
a = r_[0:16].reshape(4,4) a.max() a.min(1) a.mean(0) a.mean(1) a.sum(1)
Tambi n podemos seleccionar a los elementos de un arreglo que satisfacen cierta propiedad: e
a > 5 a[a > 5] = 0
Adem s existe una funci n where, que es como una versi n vectorizada de if: a o o
b = r_[0:16].reshape(4,4) c = list(b.flatten()) c.reverse() c = array(c).reshape(4,4) a = where(b < 5, b, c)
22
Este comando pone cada entrada de a igual a la entrada correspondiente de b si esta es menor que 5, o a la de c si no.
6.10.
Numeros aleatorios
La biblioteca numpy incluye un m dulo amplio para manipular n meros aleatorios, llamado random. Como o u siempre, las funciones se llaman, por ejemplo, random.random(). Para facilitarnos la vida, podemos importar todas estas funciones al espacio de nombres con
from numpy import * random? # informacion sobre el modulo from random import * # 'random' esta
o
from numpy.random import *
N tese que hay otro m dulo random que existe afuera de numpy, con distinta funcionalidad. o o La funcionalidad b sica del m dulo es la de generar n meros aleatorios distribuidos de manera uniforme en el a o u intervalo [0, 1):
random() for i in xrange(10): random()
Al poner random(N), nos regresa un vector de n meros aleatorios de longitud N. u Para generar una matriz aleatoria, podemos utilizar
rand(10, 20)
Tambi n hay diversas funciones para generar n meros aleatorios con distribuciones no-uniformes, por ejemplo e u exponential(10) y randn(10,5,10) para una distribuci n normal, o binomial(10,3,100). o Ejercicio: Calcula la distribuci n de distancias entre valores propios consecutivos de una matriz aleatoria real o y sim trica. e
6.11.
Transformadas de Fourier
Otro subm dulo util de numpy es fft, que provee transformadas r pidas de Fourier: o a
from numpy import * x = arange(1024) f = fft.fft(x) y = fft.ifft(f) linalg.norm( x - y )
Captulo 7
7.1.
Entorno pylab
El paquete matplotlib dibuja las gr cas. Para integrar mejor este m dulo con el uso interactivo, y en a o particular con ipython, incluye un m dulo pylab, que provee muchos comandos de utilidad para manejar o matplotlib. La manera m s efectiva de cargar la biblioteca pylab es al mero momento de correr ipython: se da la opci n a o -pylab en la lnea de comandos1 :
> ipython -pylab
Si todo funciona correctamente, deberas recibir el mensaje Welcome to pylab, a matplotlib-based Python environment. En este caso, ya se habr cargado el entorno pylab, que incluye el m dulo matplotlib para a o llevar a cabo gr cas, y tambi n carga autom ticamente numpy, por lo cual no es necesario volver a cargar estos a e a m dulos para uso interactivo. [S es necesario cargarlos explcitamente en cualquier script que ocupe gr cas.] o a
7.2.
Gr cas b sicas a a
El comando principal de matplotlib / pylab es plot. Acepta uno o dos listas o vectores de numpy, que corresponden a las coordenadas y (si hay un solo vector) o x y y de una gr ca 2D. Por ejemplo, si queremos a gracar los cuadrados de los n meros de 1 a 10, podemos hacer u
x = arange(10) y = x * x plot(x, y)
al estilo de MATLAB. (De hecho, pylab se cre bas ndose en el comportamiento de MATLAB.) o a N tese que por defecto las gr cas se acumulan. Este comportamiento se puede modcar con hold(False), o a que reemplaza las gr cas con las nuevas, y hold(True), que regresa a la funcionalidad por defecto. Tambi n a e se puede utilizar clf() para limpiar la gura.
encuentro conveniente declarar un nuevo comando pylab agregando la lnea alias pylab=ipython -pylab en el archivo .bashrc en mi directorio hogar.). Entonces se puede correr simplemente a poner pylab en la lnea de comandos.
1 Yo
23
24
La ventana que cree matplotlib incluye botones para poder hacer acercamientos y moverse a trav s de la e gr ca. Tambi n incluye un bot n para exportar la gura a un archivo en distintos formatos. Los formatos de a e o principal inter s son PDF, que es un formato vectorial (que incluye las instrucciones para dibujar la gura), e que da la calidad necesaria para las publicaciones, y PNG, que da una imagen de la gura, y es adecuada para p ginas web. a
7.3.
Cambiando el formato
Hay distintos tipos de lneas y puntos disponibles, y se puede modicar el tama o de ambos. Todas las opciones n est n disponible a trav s de la documentaci n de plot, a trav s de plot?. Adem s, los colores se pueden a e o e a especicar explcitamente:
x = arange(10) plot(x, x**2, 'ro', x, 2*x, 'gx') plot(x, 3*x, 'bo-', linewidth=3, markersize=5, markerfacecolor='red', markeredgecolor='green', mar
Se pueden dar cualquier n mero de gr cas que dibujar en un solo comando. Si el formato no se da explcitau a mente, entonces matplotlib escoge el siguiente de una secuencia razonable de estilos.
7.4.
Etiquetas
7.5.
Una vez que una gura se vuelve complicada, es necesario recurrir a un script que contenga las instrucciones para dibujarla. Eso es sumamente importante en particular para preparar guras para un documento, donde se ajustar varias veces una sola gura hasta que quede bien. a Para utilizar matplotlib desde un script, es necesario incluir la biblioteca pylab. Luego se puede utilizar plot. Para ver la imagen, a veces es necesario poner el comando show():
25
Eso tambi n es necesario al utilizar pylab desde ipython sin poner ipython-pylab, pero en este caso, es e necesario cerrar la gr ca para poder volver a utilizar el ipython. a
7.6.
Escalas logartmicas
Para utilizar ejes con escalas logartimicas, hay tres funciones: loglog, semilogy y semilogx. Se utilizan en lugar de plot:
t = arange(1000) p = t**(-0.5) loglog(t, p, 'o')
7.7.
Multiples dibujos
Es decir, se especican el n mero de renglones y columnas que uno quiere, y el ultimo n mero especica cu l u u a dibujo es los num_renglones num_columnas es. Aqu est un ejemplo adaptado de la documentaci n de a o matplotlib:
def f(t): """Oscilacion amortiguada""" c = cos(2*pi*t) e = exp(-t) return c*e t1 = arange(0.0, 5.0, 0.1) t2 = arange(0.0, 5.0, 0.02) t3 = arange(0.0, 2.0, 0.01) subplot(211) l = plot(t1, f(t1), 'bo', t2, f(t2), 'k--', markerfacecolor='green') grid(True) title('Amortiguacion de oscilaciones') ylabel('Amortiguada') subplot(212) plot(t3, cos(2*pi*t3), 'r.') grid(True) xlabel('tiempo $t$ (s)') ylabel('No amortiguada') show()
7.8.
Animaciones
Las gr cas hechas en matplotlib se pueden animar. La manera m s f cil es simplemente redibujar la gr ca a a a a completa cada vez que se cambian los datos. Sin embargo, eso no es eciente, ya que se tiene que recalcular cada vez las etiquetas etc.
26
Una mejor soluci n es que cada vez se cambie simplemente el contenido de datos de la gr ca. Primero es o a necesario asignarle a la gr ca un nombre: a
from pylab import * x = arange(10) y = x*x ion() p, = plot(x, y) for a in arange(0, 10, 0.1): x = arange(10) + a p.set_xdata(x) draw()
N tese el comando ion() (interactividad prendida). El comando p, = plot(x,y) es necesario ya que el o comando plot regresa una lista de todos los objetos en el plot. Se utiliza esta asignaci n de tuplas para extraer o realmente el primer elemento; sera equivalente (pero menos natural) poner p = plot(x,y)[0].
7.9.
Aparte del tipo b sico de gr cas que hemos visto hasta ahora, que permiten llevar a cabo gr cas de datos a a a como puntos y/o lneas, existe en matplotlib una gran variedad de otros tipos de gr cas posibles; se reere a a la p gina principal http://matplotlib.sourceforge.net y a la p gina http://www.scipy. a a org/Cookbook/Matplotlib que contiene muchos ejemplos. Por ejemplo, podemos visualizar matrices 2D como heat-maps (mapas en los cuales el color corresponde al valor de la matriz) con pcolor y imshow. N tese que para crear una gura cuadrada, se puede utilizar o
f = figure( figsize=(8,8) )
Otro tipo de gr ca disponible es un histograma. pylab puede calcular y dibujar la gr ca en un solo comando: a a
from pylab import randn, hist x = randn(10000) hist(x, 100, normed=True)
Hay una funci n histogram en numpy que calcula histogramas sin dibujarlos. o Aqu va una versi n tomada de la documentaci n: o o
import numpy as np import matplotlib.mlab as mlab import matplotlib.pyplot as plt mu, sigma = 100, 15 x = mu + sigma*np.random.randn(10000) # the histogram of the data n, bins, patches = plt.hist(x, 50, normed=1, facecolor='green', alpha=0.75) # add a 'best fit' line y = mlab.normpdf( bins, mu, sigma) l = plt.plot(bins, y, 'r--', linewidth=1) plt.xlabel('Smarts') plt.ylabel('Probability') plt.title(r'$\mathrm{Histogram\ of\ IQ:}\ \mu=100,\ \sigma=15$') plt.axis([40, 160, 0, 0.03])
27
7.10.
Para usos m s avanzados de matplotlib, es necesario entender mejor la estructura interna del paquete, que a es justamente lo que esconde pylab. Por ejemplo, para colocar una echa en un dibujo, utilizamos patches (parches):
from pylab import * x = arange(10) y = x plot(x, y) arr = Arrow(2, 2, 1, 1, edgecolor='white') ax = gca() # obtener el objeto tipo "eje" ("axis") ax.add_patch(arr) arr.set_facecolor('g') show()
7.11.
Por lo tanto, es necesario primero construir la malla donde se calcular el campo vectorial. Esto se hace con a
meshgrid, que acepta dos vectores 1D que dan las coordenadas x y y de los puntos de la malla. meshgrid
construye una malla cuyos v rtices son los puntos en el producto cartesiano de los dos conjuntos de puntos. e Regresa una tupla de dos matrices, que dan las coordenadas x y y respectivamente de los puntos de la malla:
x = r_[-5:5:11j] y = r_[-5:5:11j] X, Y = meshgrid(x, y) print X, Y
As que meshgrid en alg n sentido provee un mapa de las entradas de la matriz a sus coordenadas en el u espacio real 2D. El punto de esta construcci n es que ahora las funciones se pueden evaluar en cada punto de la red al mismo o tiempo. Por ejemplo, para tener una matriz que representa la suma de las componentes x y y en cada punto de la malla, hacemos
Z = X + Y
Una abreviaci n del comando meshgrid, usando una notaci n indicial parecida a la que ocupa r_, es o o
X, Y = mgrid[-5:5:11j, -5:5:11j]
28
7.12.
Campos vectoriales
Los campos vectoriales se pueden dibujar con la funci n quiver2 . Esta funci n acepta 4 matrices, X y Y o o que dan las coordenadas X y Y de los puntos de la malla donde se especica el campo, y U y V , que son las componentes de los vectores que dibujar en cada punto. Por ejemplo, podemos dibujar un campo radial al poner
X, Y = mgrid[-5:5:11j, -5:5:11j] quiver(X, Y, X, Y)
ya que en el punto (x, y) de la malla ponemos el vector (x, y). Lo podemos colorear seg n el valor de la distancia u del origen con
X, Y = mgrid[-5:5:11j, -5:5:11j] R = sqrt(X*X + Y*Y) quiver(X, Y, X, Y, R)
Resulta que se ven un poco deformados, ya que cada echa se dibuja empezando en el punto dado de la malla. Se ve m s ordenado al colocar el punto medio de la echa en el punto de la malla: a
quiver(X, Y, Y, X, R, pivot='middle')
7.13.
Gr cas en 3D a
En versiones recientes de matplotlib, hay soporte limitado para gr cas en 3D. El m dulo relevante es a o mplot3d. Un ejempo tomado de la documentaci n: o
from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm import matplotlib.pyplot as plt import numpy as np fig = plt.figure() ax = Axes3D(fig) X = np.arange(-5, 5, 0.25) Y = np.arange(-5, 5, 0.25) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet) plt.show()
7.14.
Se puede interactuar con el mouse y con el teclado de una manera relativamente sencilla. Para interactuar con el mouse, creamos una funci n que se llamar cuando pylab note que hay un evento o a que involucre el mouse. Esta funci n toma un solo argumento, que suele llamarse event. pylab manda a la o
2 Eso
es una broma nerd: quiver quiere decir carcaj (un objeto donde se guardan las echas).
29
funci n un objeto que representa el evento, incluyendo cu l bot n se presion y en que posici n de la gr ca. o a o o o a La funci n se registra ante pylab con la funci n connect. o o Lo mismo tiene para el teclado. As que el c digo m s sencillo es el siguiente. N tese que es necesario que o a o haya una gr ca pre-existente antes de poder interactuar con ella. a
from pylab import * def teclado(event): print "Se tecleo %s en la posicion ( %g, %g)" % event.key, event.xdata, event.ydata def mouse(event): if event.button != 1: return x,y = event.xdata, event.ydata print "Se oprimio el boton izquierdo en ( %g, %g)" % (x, y) x = arange(10) y = x*x p, = plot(x, y) show() connect('button_press_event', mouse) connect('key_press_event', teclado)
30
Captulo 8
Veamos unas rutinas y herramientas para integrar ecuaciones diferenciales. Ocuparemos las t cnicas b sicas e a que se ven en el curso de Fsica Computacional los m todos de Euler y RungeKutta. e La ecuaci n que resolveremos es o x = f(x). Recordemos que eso es una notaci n para decir que o x(t) = f(x(t)). (8.2) (8.1)
Es decir, si estamos en el punto x(t) al tiempo t, entonces la derivada instant nea en este momento y este punto a del espacio fase est dada por f(x(t)). a Para resolver esta ecuaci n en la computadora, es necesario discretizarla de una manera u otra. La manera m s o a sencilla para hacerlo es discretizando el tiempo en pasos iguales de tama o t y aproximando la derivada por n una diferencia nita, o sea expandiendo en una serie de Taylor, lo cual da x(t + t) x(t) + t x(t) + O((t)2 ) = x(t) + hf(x(t)) + O((t)2 ), (8.3)
donde h = t es el paso de tiempo. Eso nos da el m todo de Euler. Lo podemos implementar como una funci n e o que regresa el valor nuevo de la variable:
def euler(t, x, h, f): return x + h*f(x)
N tese que la funci n euler toma el nombre de la funci n f que integrar como argumento. o o o Ahora para integrar la ecuaci n entre un tiempo initial t0 y un tiempo nal t f , repetimos este paso muchas o veces:
def integrar(t0, tf, h, x0, f): lista_t = [] lista_x = [] x = x0 for t in arange(t0, tf+h/2., h): x = euler(t, x, h, f) lista_t.append(t) lista_x.append(x) return lista_t, lista_x
31
32
N tese que el mismo c digo funciona para ecuaciones vectoriales x = f(x), siempre y cuando la funci n f o o o acepte un vector y regresa un vector. Si tenemos varios m todos, entonces cambiamos la denici n de integrar a e o
def integrar(t0, tf, h, x0, f, metodo):
Captulo 9
9.1.
Redirecci n o
En esta secci n veremos algunas t cnicas utiles del shell bash que no est n restringidos a python. o e a Ya hemos visto que la manera m s f cil de guardar informaci n en un archivo es con la redirecci n de la salida a a o o est ndar del programa: corriendo desde la terminal, ponemos a
python prog.py > salida.dat
y as creamos un archivo salida.dat, donde se capta la informaci n que anteriormente se mandaba a la o terminal. Lo mismo se puede hacer con la entrada est ndar: si tenemos un programa que lee informaci n que teclea el a o usuario:
a = raw_input("Dame a: ") b = raw_input("Dame b: ")
Entonces podemos tambi n mandarle valores de un archivo, al redirigir la entrada est ndar: e a
python prog.py < datos.dat
donde datos.dat contiene la informaci n deseada. A su vez, la salida de este programa se puede mandar a o otro archivo con >. Finalmente, si queremos conectar la salida de un programa con la entrada de otro, utilizamos un tubo (pipe):
python prog1.py | python prog2.py
pero sin la necesidad de crear el archivo temporal. Los pipes son muy utiles en unix, y se pueden encadenar. 33
34
9.2.
Una manera m s exible y m s util para mandar informaci n a un programa es a trav s de argumentos que se a a o e ponen en la mera lnea de comandos. A menudo queremos mandar a un programa los valores de un par metro, a para despu s poder hacer barridos del mismo. e Para hacerlo, Python provee una variable llamada argv, que viene denida en el m dulo sys. Podemos ver o qu es lo que contiene esta variable al correr un programa sencillo: e
from sys import argv print "Argumentos: argv"
entonces vemos que argv es una lista de cadenas, cada una representando uno de los argumentos, empezando por el nombre del script. Por lo tanto, podemos extraer la informaci n deseada con las herramientas normales o de Python, por ejemplo
from sys import argv T, h = map(float, argv[1:3]) modelo = argv[3]
Sin embargo, si no damos sucientes argumentos, entonces el programa fracasar . Podemos atrapar una excepa ci n de este tipo con un bloque try. . . except: o
from sys import argv, exit try: T, h = map(float, argv[1:3]) modelo = argv[3] except: print "Sintaxis: python prog.py T h modelo" exit(1)
Es util proveerle al usuario informaci n acerca de la raz n por la cual fracas el programa. Aqu hemos utilizado o o o la funci n exit que viene tambi n en el m dulo sys, para que salga del programa al encontrar un problema, o e o pero eso no es obligatorio podra poner valores por defecto de los par metros en este caso, por ejemplo. a
9.3.
El m dulo os provee unas herramientas para mandar llamar a otros programas hijos desde un programa o padre1 . La funci n m s util es system, que permite correr un comando a trav s de un nuevo bash; podemos enviar o a e cualquier comando que funciona en bash, en particular podemos correr otros programas. La funci n acepta o una cadena:
from os import system system("ls")
Ahora podemos empezar a hacer cosas interesantes al construir los comandos con la sustituci n de variables. o Por ejemplo, si tenemos un programa prog.py que acepta un argumento de la lnea de comandos, podemos correrlo de manera consecutiva con distintos valores del par metro con a
1 Hoy
en da, se recomienda m s bien el paquete subprocess para esta funcionalidad, pero es m s complicado. a a
9.4. EJEMPLOS
for T in range(10): comando = "python prog.py %g" % T system(comando)
35
Si queremos abrir un programa que se conectar al nuestro y recibir comandos, utilizamos popen para abrir a a un pipe:
from os import popen gp = popen("gnuplot -persist", "w") gp.write("plot sin(x)\n") gp.close()
Una manera f cil de hacer una animaci n es utilizar la terminal de GIF animado en gnuplot. Para utilizar esta a o terminal, es necesario contar con una versi n de gnuplot compilada de manera adecuada, con la librera gd. o En la terminal de GIF animado, cada vez que uno ejecuta un plot, otro cuadro se agrega a la animaci n. Por o ejemplo:
from os import popen from numpy import arange gp = popen("gnuplot", "w") gp.write("set term gif anim\n") gp.write("set out 'sin.gif'\n") # archivo de salida de gnuplot for a in arange(0., 10., 0.1): gp.write("plot sin(x + %g)\n title 'sin(x+ %g)'\n" % (a, a) ) gp.write("set out\n") # cerrar el archivo de salida de gnuplot gp.close()
9.4.
Ejemplos
Veamos algunos ejemplos de lo que podemos hacer utilizando Python para controlar otros programas. La sustituci n de variables juega un papel crucial. o
9.4.1.
A Empecemos con una aplicaci n sencilla, en la cual utilizamos Python para crear un archivo de LTEX para una o carta de aceptaci n de un congreso, para la cual necesitamos el nombre del autor y el ttulo del cartel. o A Primero, para generar un archivo de LTEX, necesitamos poder manejar ciertos caracteres especiales en las cadenas. Para hacerlo, podemos poner r al principio de la cadena para formar una cadena raw (crudo); Python autom ticamente la convertir en una cadena normal: a a
s = r"\begin{document}" s print s
Adem s, Python nos permite declarar cadenas con varias lneas, al utilizar tres comillas. As que un archivo de a A LTEX sencillo se puede crear con
codigo_latex = r""" \documentclass{article} \usepackage{mathptmx} % fuente Times \begin{document} <Hola, David! \end{document} """
36
Ahora est f cil reemplazar el nombre con el contenido de una variable, por ejemplo una que leemos de la lnea a a de comandos, con el siguiente c digo que guardamos como saludo.py: o
from sys import argv, exit try: nombre = argv[1] except: print "Sintaxis: python saludo.py nombre" exit(1) codigo_latex = r""" \documentclass{article} \usepackage{mathptmx} % fuente Times \begin{document} <Hola, %s! \end{document} """ % nombre
Lo guardamos y compilamos como antes. N tese que la sustituci n de variables tambi n se puede utilizar con o o e las cadenas crudas y las con m ltiples lneas. u
A Incluso podramos leer el c digo LTEX desde un archivo. En el archivo ponemos %s etc. donde queremos o sustituir variables. Leemos el contenido del archivo en una cadena, que entonces contendr explcitamente los a %s, y luego hacemos la sustituci n. As, si temp.tex contiene o
podemos hacer
entrada = open("temp.tex", "r") codigo_latex = entrada.read() # leer todo el contenido en una cadena nombre = "David" codigo_latex = codigo_latex % nombre
En la ultima lnea, reemplazamos el contenido de codigo_latex con el resultado de hacer la sustituci n de o variables.
9.4. EJEMPLOS
37
9.4.2.
Gr cas del comportamiento de un sistema para distintos valores de un par mea a tro
A Ahora veamos un ejemplo m s complicado, tambi n ocupando LTEX, donde crearemos un archivo con vaa e rias guras que retratan el comportamiento de un sistema con distintos valores de un par metro. Esta idea se a tom del excelente libro de Langtangen. Ah se dan varias variaciones sobre el tema, incluyendo c mo generar o o un reporte en HTML.
Lo primero que hay que hacer es generar las guras. Esto se puede hacer por ejemplo con gnuplot, pero aqu emplearemos pylab. Para enfatizar la idea, nuestro sistema ser una gr ca de sin(kx) para distintos k, a a pero basta con reemplazar la gr ca con datos reales. Primero generemos una gr ca: a a
from pylab import * t = arange(-2*pi, 2*pi, 0.1) plot(t, sin(t), '-o') savefig("sin.pdf")
N tese el uso directo de la sustituci n de variables para generar la cadena correspondiente al nombre del archivo o o A al momento de utilizarla. Acord monos que pylab puede ocupar directamente etiquetas hechas con LTEX. e
A Ahora agarremos estas guras y pong moslas en un solo PDF, a trav s de LTEX. Para hacerlo, primero generea e mos el principio del archivo:
latex = r""" \documentclass{article} \usepackage{graphicx} % para incluir figuras \begin{document} \begin{figure} """
A Ahora para cada gura, tenemos que agregar el comando de LTEX para importarla:
N tese que es necesario separar el \n para que no aparezca adentro de la cadena cruda. Finalmente hay que o terminar la gura:
latex += "\end{figure}"
38
adentro de entorno figure como sigue: \subfigure[subpie]{\includegraphics{subfigura}}, donde subpie es el pie de gura para la subgura, y subfigura el archivo. As que podemos poner:
subfigura = r""" \subfigure[$k= %d$] { \includegraphics[scale=0.4]{sin %d} } """ # cada figura se ve a s # Ahora incluir cada figura: for k in range(1, 7): latex += subfigura % (k, k)
Captulo 10
10.1.
Consideremos una situaci n cl sica en el c mputo cientco: un sistema que consiste en cierto n mero de o a o u partculas en 2 dimensiones, que tienen propiedades internas, como una posici n, una velocidad y una masa, y o que se pueden mover con una regla tipo Euler. Para una partcula, podramos denir sus variables simplemente como sigue:
x = y = 0.0 # posicion vx = vy = 1.0 # velocidad
Si las partculas tambi n tienen masas y colores, entonces se vuelve muy tedioso, ya que tenemos que actualizar e todo dos veces para cada propiedad nueva:
m1 = m2 = 0.0; c1 = c2 = 0.0;
Para muchas particulas podramos emplear arreglos (listas, en Python), que reducira el trabajo. Pero ahora podramos imaginarnos que por alguna raz n queremos agregar otra partcula, o incluso duplicar o toda la simulaci n. Entonces tendramos que duplicar a mano todas las variables, cambiando a la vez sus o nombres, lo cual seguramente conducir a introducir errores. a Sin embargo, conceptualmente tenemos muchas variables que est n relacionadas: todas pertenecen a una a partcula. Hasta ahora, no hay manera de expresar esto en el programa. 39
40
10.2.
Lo que queremos hacer, entonces, es reunir todo lo que corresponde a una partcula en un nuevo tipo de objeto, llamado Particula. Luego podremos decir que p1 y p2 son Particulas, o incluso hacer un arreglo (lista) de Particulas. Toda la informaci n que le corresponde a una partcula dada estar contenida adentro del objeto; esta informao a ci n formar parte del objeto no s lo conceptualmente, sino tambi n en la representaci n en el programa. o a o e o Podemos pensar en un objeto, entonces, como un tipo de caja negra, que tiene propiedades internas, y que puede interactuar de alguna manera con el mundo externo. No es necesario saber o entender qu es lo que hay e adentro del objeto para entender c mo funciona. Se puede pensar que corresponde a una caja con palancas, o botones y luces: las palancas y los botones proveen una manera de darle informaci n o instrucciones a la caja, o y las luces dan informaci n de regreso al mundo externo. o Para implementar eso en Python, se declara una clase llamada Particula y se crea una instancia de esta clase, llamada p.
class Particula: x = 0.0 p = Particula() p.x
N tese que p tiene adentro una propiedad, que se llama x. Podemos interpretar p.x como una x que le pertenece o a p. Si ahora hacemos
p2 = Particula() p2.x
entonces tenemos una variable completamente distinta que tambi n se llama x, pero que ahora le pertenece a e p2, que es otro objeto de tipo Particula. De hecho, m s bien podemos pensar que p2.x es una manera de a escribir p2_x, que es como lo hubi ramos podido escribir antes, que tiene la bondad de que ahora tamben e tiene sentido pensar en el conjunto p como un todo. Remarquemos que ya estamos acostumbrados a pensar en cajas de este tipo en matem ticas, al tratar con a vectores, matrices, funciones, etc.
10.3.
M todos de clases e
Hasta ahora, una clase act a simplemente como una caja que contiene datos. Pero objetos no s lo tienen u o informaci n, sino tambi n pueden hacer cosas. Para hacerlo, tambi n se pueden denir funciones llamadas o e e m todos que le pertenecen al objeto. Simplemente se denen las funciones adentro de la declaraci n de la e o clase:
class Particula: x = 0.0 v = 1.0 def mover(self, dt): self.x += self.v*dt p = Particula() print p.x p.mover(0.1) print p.x
41
N tese que los m todos de las clases siempre llevan un argumento extra, llamado self, que quiere decir o e s mismo. Las variables que pertenecen a la clase, y que se utilizan adentro de estas funciones, llevan self., para indicar que son variables que forman parte de la clase, y no variables globales. Podemos pensar en las variables internas a la clase como variables pseudo-globales, ya que est n accesibles desde cualquier lugar a adentro de la clase.
10.4.
Funciones inicializadoras
Cuando creamos una instancia de un objeto, muchas veces queremos inicializar el objeto al mismo tiempo, es decir pasarle informaci n sobre su estado inicial. En Python, esto se hace a trav s de una funci n inicializadora, o e o como sigue:
class Particula: def __init__(self, xx=0.0, vv=1.0): self.x = xx self.v = vv def mover(self, dt): self.x += self.v*dt p1 = Particula() print p1.x p2 = Particula(2.5, 3.7) print p2.x p1.mover(0.1) p2.mover(0.1) print p1.x, p2.x
N tese que la funci n inicializadora debe llamarse __init__, con dos guiones bajos de cada lado del nombre o o init. Puede tomar argumentos que se utilizan para inicializar las variables de la clase.
10.5.
Las clases pueden ocupar varios m todos para proveer un interfaz m s limpio para el usuario. Por ejemplo, al e a poner printp1 en el ultimo ejemplo, sale algo as como
<__main__.Particula instance at 0x2849cb0>
Podemos hacer que salga algo m s util al proveer adentro de la clase una funci n __str__: a o
class Particula: def __init__(self, xx=0.0, vv=1.0): self.x = xx self.v = vv def __str__(self): return "Particula( %g, %g)" % (self.x, self.v) p1 = Particula() print p1
Tambi n podemos denir funciones que permiten que podamos llevar a cabo operaciones aritm ticas etc. con e e objetos de este tipo, es decir, podemos sobrecargar los operadores para que funcionen con nuestro nuevo tipo. Eso es lo que pasa con los array de numpy, por ejemplo. Ejercicio: Haz un objeto para representar a una partcula en 2D. Haz una nube de tales partculas.
42
10.6.
Herencia
Las clases tambi n pueden formar jerarquas al utilizar la herencia, que quiere decir que una clase es un tipo e de, o subtipo de otro.
Captulo 11
11.1.
El paquete scipy provee una colecci n de herramientas para llevar a cabo tareas num ricas, como son los sio e guientes subm dulos: funciones especiales (special); integraci n de funciones y de ecuaciones diferenciales o o ordinarias (integrate), optimizaci n y races de funciones (optimize), algebra lineal (linalg), incluyendo o para matrices escasas (sparse), y estadsticas (stats). Veamos algunos ejemplos. Para utilizar las funciones especiales, hacemos
from scipy import special for i in range(5):
Para integrar la ecuaci n de Airy (un ejemplo de la documentaci n de scipy) o o d2w zw(z) = 0, dz2 podemos poner
from from y1_0 y0_0 y0 = scipy.integrate import odeint scipy.special import gamma, airy = 1.0/3**(2.0/3.0)/gamma(2.0/3.0) = -1.0/3**(1.0/3.0)/gamma(1.0/3.0) [y0_0, y1_0]
(11.1)
43
44
x = arange(0,4.0, 0.01) t = x ychk = airy(x)[0] y = odeint(func, y0, t) y2 = odeint(func, y0, t, Dfun=gradient) print ychk[:36:6] print y[:36:6,1] print y2[:36:6,1]
En la segunda llamada a odeint, mandamos explcitamente la funci n que calcula la derivada (gradiente) de o f; en la primera llamada, no fue necesario contar con una funci n que calculara eso. o Encontrar races de funciones es m s o menos sencillo: a
def f(x): return x + 2*cos(x) def g(x): out = [x[0]*cos(x[1]) - 4] out.append(x[1]*x[0] - x[1] - 5) return out from scipy.optimize import fsolve x0 = fsolve(func, 0.3) x02 = fsolve(func2, [1, 1])
11.2.
El m dulo sympy provee una colecci n de rutinas para hacer c lculos simb licos. Las variables se tienen que o o a o declarar como tal, y luego se pueden utilizar en expresiones simb licas: o
from sympy import * x, y, z = symbols('xyz') k, m, n = symbols('kmn', integer=True) f = Function("f") x + x (x + y) ** 2 z = _ z.expand() z.subs(x, 1) limit(sin(x) / x, x, 0) limit(1 - 1/x, x, oo) diff(sin(2*x), x) diff(sin(2*x), x, 3) cos(x).series(x, 0, 10) integrate(log(x), x) integrate(sin(x), (x, 0, pi/2))
11.3. MAYAVI2
f(x).diff(x, x) + f(x) dsolve(f(x).diff(x, x) + f(x), f(x)) solve(x**4 - 1, x) pi.evalf(50)
45
11.3. mayavi2
El paquete mayavi2 provee una manera de visualizar conjuntos de datos complejos en 3D. Para utilizarlo de manera interactiva, comenzamos con
ipython -wthread import numpy as np def V(x, y, z): """ A 3D sinusoidal lattice with a parabolic confinement. """ return np.cos(10*x) + np.cos(10*y) + np.cos(10*z) + 2*(x**2 + y**2 + z**2) X, Y, Z = np.mgrid[-2:2:100j, -2:2:100j, -2:2:100j] V(X, Y, Z) from numpy import * from enthought.mayavi import mlab x, y, z = random.rand(3, 10) mlab.points3d(x, y, z) c = random.rand(10) mlab.points3d(x, y, z, color=c) mlab.clf() mlab.contour3d(X, Y, Z, V)
11.4.
El paquete sage, disponible libremente de la p gina http://www.sagemath.org, pretende proveer una a manera de reemplazar a programas del estilo de Mathematica, al proveer un entorno completo para hacer c lculos matem ticos. Es un entorno que provee un interfaz tipo Python a muchos paquetes libres para hacer a a matem ticas. Adem s, provee un interfaz disponible por el internet para interactuar con los notebooks. a a