Apuntes PDF
Apuntes PDF
1 Introducción a Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1 Instalación de Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Manejo básico de Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 IPython Notebook. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2 El lenguaje Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1 Aspectos básicos del lenguaje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 Módulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.3 Control de flujo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.4 Funciones definidas por el usuario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.5 Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3 Aspectos avanzados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.1 Algo más sobre funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.2 Entrada y salida de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.3 Más sobre estructuras de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.4 Excepciones. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.5 Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4 NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.1 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.2 Funciones para crear y modificar arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
1
2 ÍNDICE GENERAL
4.3 Slicing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.4 Operaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4.5 Broadcasting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.6 Otros métodos de interés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.7 Indexación sofisticada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
4.8 Operaciones con slicing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.9 Lectura de ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
4.10 Búsqueda de información . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
4.11 Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
5 SciPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.1 Optimización sin restricciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.2 Optimización con restricciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
5.3 Interpolación de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
5.4 Resolución de ecuaciones diferenciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
5.5 Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
1 1
INSTALACIÓN DE PYTHON
Python viene instalado por defecto en los sistemas Linux y OSX, y se puede
instalar de forma sencilla en los sistemas Windows desde la página oficial
www.python.org. Sin embargo, diversos módulos de interés, y entre ellos, los
dedicados a la programación científica que veremos en los Capítulos 4, 5 y
6, requieren de instalaciones separadas. Existen diversas posibilidades para
realizar la instalación de otros módulos, pero nosotros vamos a optar por una
solución simple y eficiente, que consiste en la instalación de la distribución de
Python anaconda.
anaconda Python es una distribución que contiene el núcleo básico
de Python y un conjunto de módulos entre los que se encuentran todos
los que vamos a emplear en este texto. Además incluye la consola IPyt-
hon y el entorno IPython Notebook que veremos en las siguientes sec-
ciones, entre otras herramientas de interés. La descarga de esta distribu-
ción se puede realizar desde la página de la empresa que la desarrolla
https://www.continuum.io/downloads
Allí encontraremos descargas para los sistemas Linux, Windows y Mac en
versiones para 32 y 64 bits, y en la versión 2.7 o 3.5 de Python. Como hemos
comentado antes, aquí usaremos la versión 2 de Python, por lo que habría que
descargar el instalador para la versión 2.7. En la misma página de descarga
tenemos instrucciones directas para su instalación, que son bastante simples.
Durante la instalación en los sistemas Windows se pregunta si queremos
que el intérprete Python que instala anaconda sea el intérprete por defecto
en el sistema, ya que anaconda convive bien con otras versiones de Python
en el mismo sistema, y si queremos añadir anaconda a la variable PATH.
Responderemos afirmativamente a ambas cuestiones. De igual modo, en los
sistemas Linux se nos pedirá que ajustemos la variable PATH del sistema para
que esté accesible el entorno anaconda.
Una vez instalado, podemos ejecutar el programa anaconda-navigator
que aparece en la lista de programas (en Windows) o desde la consola en
Linux, que nos permitirá ejecutar alguno de los programas que comentaremos
en la siguiente sección.
1 2
MANEJO BÁSICO DE PYTHON
Por ejemplo en Windows, podemos abrir una terminal con el programa Anaconda Prompt
instalado con la distribución anaconda.
2 Para diferenciar la escritura de órdenes en el intérprete de los comandos que introduci-
el fichero con Notepad, por ejemplo, a la hora de guardarlo deberíamos seleccionar All Files
en el tipo de archivo. En caso contrario se guardará con extensión .txt.
4 Esto es lo que se conoce como el shebang, y es el método estándar para poder ejecutar un
programa interpretado como si fuera un binario. Windows no tiene soporte para el shebang.
6 Capítulo 1 Introducción a Python
1 2 2 La consola IPython
En lugar del intérprete Python habitual existe una consola interactiva
denominada IPython con una serie de características muy interesantes que
5 Es decir, codificaciones que admiten caracteres acentuados.
1.2 Manejo básico de Python 7
In [1]:
In [2]:
Si como ocurre en este caso, nuestra entrada produce una salida Out[1]:
46, podemos usar la numeración asignada para reutilizar el dato mediante la
variable _1,
In [2]: _1 + 15
Out [2]: 61
In [4]: _2 + _
Out [4]: 183
Además, esta consola pone a nuestra disposición comandos del entorno (cd
, ls, etc.) que nos permiten movernos por el árbol de directorios desde dentro
de la consola, y comandos especiales, conocidos como funciones mágicas que
proveen de funcionalidades especiales a la consola. Estos comandos comienzan
6 Desde Anaconda Navigator disponemos de esta terminal a través de Jupyter QtConsole.
8 Capítulo 1 Introducción a Python
1 3
IPYTHON NOTEBOOK
# Cabecera
↱
y a continuación pulsamos + , que supone la ejecución del contenido de
la celda, obtendremos:
Cabecera
que es el resultado de interpretar el símbolo # antes de una palabra, que supone
darle formato de título de primer nivel. Si la entrada hubiera sido:
### Cabecera
legible un texto.
10 Capítulo 1 Introducción a Python
2 1
ASPECTOS BÁSICOS DEL LENGUAJE
2 1 1 Variables numéricas
Veamos algunos ejemplos:
a = 2 # define un entero
b = 5. # define un número real
c = 3+1j # define un número complejo
d = complex (3 ,2) # define un número complejo
7
2
Claramente a+b calcula la suma de los valores de las variables, sin embargo
a/b parece que no calcula correctamente la división. En realidad la respuesta
es correcta dado que ambas variables son enteros, y por tanto se realiza la
división entre enteros, que corresponde a la parte entera de la división. Esto
es lo que se conoce como el carácter fuertemente tipado de Python.
Si lo que esperamos es obtener la división real debemos escribir al menos
uno de los números en forma real, lo que se hace con el comando float:
a/ float(b)
2.5
(5+3j)
<type 'complex'>
2.1 Aspectos básicos del lenguaje 13
a = 5.; b = 3.
print a/b
print a//b
1.6666666666666667
1.0
Nótese que el resultado de la división entera entre dos reales es un real. Del
mismo modo:
print a % b
print int(a) % int(b)
2.0
2
2 1 2 Objetos
Python sigue el paradigma de la Programación Orientada a Objetos
(POO). En realidad, todo en Python es un objeto. Podemos entender un
objeto como un tipo especial de variable en la que no sólo se almacena un
valor, o conjunto de valores, sino para el que tenemos disponible también una
serie de características y de funciones concretas, que dependerán del objeto
en cuestión.
Por ejemplo, si creamos un número complejo
a = 3+2j
print a.real
print a.imag
3.0
2.0
14 Capítulo 2 El lenguaje Python
Los atributos son características de los objetos a las que se accede mediante
el operador . de la forma objeto.atributo.
Cada tipo de objeto suele tener disponible ciertos métodos. Un método es
una función que actúa sobre un objeto con una sintaxis similar a la de un
atributo, es decir, de la forma objeto.método(argumentos). Por ejemplo, la
operación de conjugación es un método del objeto complejo:
a. conjugate ()
(3−2j)
<function conjugate>
2 1 3 Listas
Las listas son colecciones de datos de cualquier tipo (inclusive listas) que
están indexadas, comenzando desde 0:
a = [ 1, 2., 3+1j, [3 ,0] ]
type(a)
<type 'list'>
print a[1]
print a[4]
2.0
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
IndexError Traceback (
most recent call last)
<ipython−input−23−7eba33f48202> in <module>()
−−−−> 1 print a[4]
Hemos definido una lista encerrando sus elementos (de tipos diversos)
entre corchetes y separándolos por comas. Podemos acceder a cada uno de los
elementos de la lista escribiendo el nombre de la lista y el índice del elemento
entre corchetes, teniendo en cuenta que el primer elemento tiene índice 0 y por
tanto el segundo corresponde al índice 1. Si intentamos acceder al elemento
a[4] obtenemos un error, pues dicho elemento no existe.
La salida de error en Python es amplia, y entre otras cosas nos marca el
lugar donde se ha producido, el tipo de error, en este caso IndexError., y en
la última línea nos da una breve explicación. En lo que sigue, para simplificar
las salidas de errores sólo mostraremos la última línea.
Si algún elemento de la lista es otra lista, podemos acceder a los elementos
de esta última usando el corchete dos veces, como en el siguiente ejemplo:
print a[3]
print a [3][1]
[3,0]
0
Las listas son estructuras de datos muy potentes que conviene aprender a
manejar con soltura. Podemos consultar los métodos a los que tenemos acceso
en una lista usando la función de autocompletado. El siguiente ejemplo es
autoexplicativo y muestra el funcionamiento de alguno de estos métodos:
25
print a
16 Capítulo 2 El lenguaje Python
−1
[0, 33, 15, 1, 33]
[0, 33, 15, 1, 33, 10, 20, 30, [10, 20, 30]]
Por otra parte, es frecuente que Python utilice los operadores aritméticos
con diferentes tipos de datos y distintos resultados. Por ejemplo, los operadores
suma y multiplicación pueden aplicarse a listas, con el siguiente resultado:
[1, 2, 3, 1, 2, 3, 1, 2, 3]
[1, 2, 3, 10, 20, 30]
a. extend (b)
print a
Nótese que el uso del método hubiera sido equivalente a escribir a=a+b. En
general, el uso de métodos proporciona mejor rendimiento que el uso de otras
acciones, pero hemos de ser conscientes de que el objeto sobre el que se aplica
puede quedar modificado al usar un método.
Slicing
Una de las formas más interesantes de acceder a los elementos de una lista
es mediante el operador de corte o slicing, que permite obtener una parte de
los elementos de una lista:
2.1 Aspectos básicos del lenguaje 17
a = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print a[2:5] # accedemos a los elementos 2,3,4
[7, 6, 5]
[8, 6, 4]
[9, 8, 7]
[3, 2, 1, 0]
print a[:20]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
[]
En las listas, y por supuesto también con el slicing, se pueden usar índices
negativos que equivalen a contar desde el final:
[4, 3]
[6, 5, 4, 3]
18 Capítulo 2 El lenguaje Python
a = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
a [1:3] = [] # borra elementos 1 y 2
print a
[9, 6, 5, 4, 3, 2, 1, 0]
[]
2 1 4 Cadenas de caracteres
Hola
mundo
<type 'str'>
en las que se puede comprobar que da igual definirlas con comillas simples o
dobles, lo que es útil si queremos cadenas que incluyan estos caracteres:
2.1 Aspectos básicos del lenguaje 19
Esto es un cadena
muy larga que tiene
muchas lineas
'H'
' '
pero las cadenas son inmutables, esto es, no es posible alterar sus elementos
(veremos este asunto más adelante en la sección 3.3.2):
Hay una gran cantidad de métodos para manejar strings que permiten
cambiar la capitalización, encontrar caracteres dentro de una cadena o separar
cadenas en trozos en función de un carácter dado. Emplazamos al lector a usar
la ayuda en línea del intérprete para aprender el funcionamiento de éstos y
otros métodos.
2 1 5 Diccionarios
colores = {'r': 'rojo ', 'g': 'verde ', 'b': 'azul '}
print type( colores )
<type 'dict'>
'rojo'
'azul'
{'k': 'negro', 'r': 'rojo', 'g': 'verde'}
2 1 6 Tuplas
Para terminar con los tipos de datos principales haremos mención a las
tuplas. Las tuplas son un tipo de dato similar a las listas (es decir, una
colección indexada de datos) pero que no pueden alterarse una vez definidas
(son inmutables):
a = (1 ,2. ,3+1j,"hola")
print type(a)
<type 'tuple'>
print a[2]
(3+1j)
<type 'tuple'>
1
2
'hola'
a = (1)
b = (1 ,)
c = 1,
print type(a), type(b), type(c)
Como veremos luego, las tuplas son útiles para pasar un conjunto de datos
a una función. También están detrás de la asignación múltiple de variables:
a,b = 0,1
b,a = a,b # intercambiamos a y b
print a, b
1 0
2 2
MÓDULOS
Ahora tenemos a nuestra disposición todas las funciones del módulo matemá-
tico. Puesto que todo en Python es un objeto (incluidos los módulos), el lector
entenderá perfectamente que el acceso a las funciones del módulo se haga de
la forma math.función:
math.sin (3.)
0.1411200080598672
Para conocer todas las funciones a las que tenemos acceso dentro del
módulo disponemos de la orden dir1
dir(math)
definidas.
24 Capítulo 2 El lenguaje Python
sqrt (2)
1.4142135623730951
import math
import cmath
math.sqrt (-1)
1j
Como vemos, hemos cargado los módulos math y cmath y calculado la raíz
cuadrada de −1 con la función sqrt que posee cada módulo. El resultado es
bien distinto: la función raíz cuadrada del módulo math no permite el uso de
números negativos, mientras que la función sqrt del módulo cmath sí. Si en
lugar de cargar los módulos como en el último ejemplo los hubiésemos cargado
así:
from cmath import *
from math import *
nos deja a nuestra disposición la función raíz cuadrada del módulo cmath y
las funciones trigonométricas seno y coseno del módulo math. Es importante
señalar que con este método de importación no tenemos acceso a ninguna
otra función de los módulos que no hubiera sido previamente importada. Esta
última opción es de uso más frecuente en los scripts, debido a que con ella
cargamos exclusivamente las funciones que vamos a necesitar y de esa forma
mantenemos el programa con el mínimo necesario de recursos.
2.2 Módulos 25
import math as m
m.cos(m.pi)
−1.0
Módulo Descripción
math Funciones matemáticas
cmath Funciones matemáticas con complejos
fractions Números racionales
os Funcionalidades del sistema operativo
sys Funcionalidades del intérprete
re Coincidencia en patrones de cadenas
datetime Funcionalidades de fechas y tiempos
pdb Depuración
random Números aleatorios
ftplib Conexiones FTP
MySQLdb Manejo de bases de datos MySQL
smtplib Envío de e-mails
26 Capítulo 2 El lenguaje Python
2 3
CONTROL DE FLUJO
2 3 1 Bucles
Una característica esencial de Python es que la sintaxis del lenguaje impone
obligatoriamente que escribamos con cierta claridad. Así, los bloques de código
deben ser obligatoriamente sangrados:
0
1
2
[5, 6, 7, 8, 9]
[1, 4, 7]
[−10, −40, −70]
hola
mundo
De igual modo que iteramos sobre una lista, puede hacerse sobre una tupla
o un diccionario. En este último caso, es posible acceder de varias formas:
colores = {'r': 'rojo ', 'g': 'verde ', 'b': 'azul '}
for i in colores .keys ():
print i, colores [i]
r rojo
b azul
g verde
r rojo
b azul
g verde
2 3 2 Condicionales
La escritura de sentencias condicionales es similar a la de los bucles for,
usando el sangrado de línea para determinar el bloque:
if 5 %3 == 0:
print "5 es divisible entre 3"
elif 5 %2 == 0:
print "5 es divisible por 2"
else:
print "5 no divisible ni por 2 ni por 3"
2 3 3 Bucles condicionados
1 1 2 3 5 8 13
Es interesante analizar un poco este breve código que genera unos cuantos
términos de la sucesión de Fibonacci. En especial, hemos de prestar atención
a cómo usamos tuplas para las asignaciones múltiples que realizamos en la
primera y última líneas; en la primera hacemos a=0 y b=1 y en la última
se realiza la asignación a=b y b=a+b, en la que debemos notar que, antes de
realizar la asignación, se evalúan los lados derechos (de izquierda a derecha).
2 es primo
3 es primo
4 es igual a 2 * 2
5 es primo
6 es igual a 2 * 3
7 es primo
8 es igual a 2 * 4
9 es igual a 3 * 3
Por último, Python dispone también de la orden pass que no tiene ninguna
acción, pero que en ocasiones es útil para estructurar código que aún no ha
sido completado, por ejemplo
2.4 Funciones definidas por el usuario 29
2 4
FUNCIONES DEFINIDAS POR EL USUARIO
Las funciones son trozos de código que realizan una determinada tarea.
Vienen definidas por la orden def y a continuación el nombre que las define
seguido de dos puntos. Siguiendo la sintaxis propia de Python, el código de
la función está sangrado. La principal característica de las funciones es que
permiten pasarles argumentos de manera que la tarea que realizan cambia en
función de dichos argumentos.
a = fibolist (250)
print a
1 1 2 3 5 8 13 21 34
print a
None
% %file tang.py
from math import sin ,cos ,pi
def tangente (x):
if cos(x) != 0:
return sin(x)/cos(x)
else:
print "La tangente es infinita "
return
x = tangente (pi)
print 'La tangente de pi es ',x
run tang.py
La tangente de pi es −1.22460635382e−16
import tang
La tangente de pi es −1.22460635382e−16
−0.1425465430742778
−1.2246063538223773e−16
Sin embargo,
print x
x = 5
from tang import *
La tangente de pi es −1.22460635382e−16
0.9999999999999999
−1.2246063538223773e−16
tendremos todas las funciones presentes en el módulo (salvo las que comiencen
por _) sin necesidad de anteponer el nombre, pero como podemos observar
32 Capítulo 2 El lenguaje Python
La tangente de pi es −1.22460635382e−16
−0.1425465430742778
NameError: name 'x' is not defined
la función tangente está disponible, pero nada más. Aun así, obsérvese que se
ha ejecutado el módulo en el momento de la importación.
Para evitar que el código se ejecute cuando importamos podemos separar
la función del resto del código del siguiente modo:
from math import sin ,cos ,pi
def tangente (x):
if cos(x) != 0:
return sin(x)/cos(x)
else:
print "La tangente es infinita "
return
2 5
EJERCICIOS
[0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105]
E.9 Escribir una función reverse que acepte una cadena de caracteres y
devuelva como resultado la cadena de caracteres invertida en orden, es decir,
el resultado de reverse('hola') debe ser 'aloh'.
E.10 Usando el Ejercicio E.9, escribir una función is_palindromo que in-
dentifique palíndromos, (esto es, palabras que leídas en ambas direcciones
son iguales, por ejemplo radar). Es decir, is_palindromo('radar') debería dar
como resultado True.
3 Aspectos avanzados
3 1
ALGO MÁS SOBRE FUNCIONES
3 1 1 Documentando funciones
Se puede documentar una función en Python añadiendo una cadena de
documentación justo detrás de la definición de función:
def mifuncion ( parametro ):
"""
Esta función no hace nada.
Absolutamente nada
"""
pass
En tal caso, la función help(mifuncion) o escribiendo mifuncion? en IPython
nos mostrará la documentación de la función.
3 1 2 Argumentos de entrada
Es posible definir funciones con un número variable de argumentos. Una
primera opción consiste en definir la función con valores por defecto:
def fibonacci (n,a=0,b=1):
sucesion = []
while b < n:
sucesion . append (b)
a,b = b,b+a
return sucesion
3.5
6.0
otro
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
(2, 3, 4)
****************************************
{}
funarg ("hola",a=2,b=4)
hola
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
()
****************************************
{'a': 2, 'b': 4}
hola
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
('uno', 'dos', 'tres')
****************************************
{'a': 2, 'c': 'fin', 'b': 3}
5.5
o en la función fibonacci,
d = {'a':5, 'b':3}
fibonacci (50 ,**d)
c = (2 ,3)
fibonacci (50 ,*c)
3 1 3 Funciones lambda
Las funciones lambda son funciones anónimas de una sola línea que pueden
ser usadas en cualquier lugar en el que se requiera una función. Son útiles para
reducir el código, admiten varios parámetros de entrada o salida y no pueden
usar la orden return:
f = lambda x,y: (x+y, x**y)
f(2 ,3)
(5, 8)
f = seno(math.pi)
g = seno (2* math.pi)
print f(.5) , g(.5)
1.0, 1.2246063538223773e−16
y ejecutamos
y luego
print area
area = 10
def area_rectangulo (lado):
area = lado*lado
return area
9
10
area = 10
def area_rectangulo (lado):
print area
area = lado*lado
return area
area = 10
def area_rectangulo (lado):
global area
print area
area = lado*lado
return area
10
9
print area
def fun(a,b):
a. append (0)
b = a+b
return a,b
a = [1]
b = [0]
print fun(a,b)
[1, 0] [1, 0, 0]
print a,b
[1, 0] [0]
Por último señalar que las variables del espacio global se pueden usar en la
definición de parámetros por defecto, pero son evaluadas sólo en la definición
de la función, y no en cada llamada:
3.2 Entrada y salida de datos 41
a = 2
def pot(x,y=a):
return x**y
pot (2) , pot (2 ,3)
(4, 8)
a = 4
pot (2)
3 2
ENTRADA Y SALIDA DE DATOS
Es habitual que nuestros programas necesiten datos externos que deben ser
pasados al intérprete de una forma u otra. Típicamente, para pasar un dato
a un programa interactivamente mediante el teclado (la entrada estándar)
podemos usar la función raw_input
Introduce algo
hola 2
'hola 2'
Como vemos, sys.argv almacena en una lista todos los datos de la llamada, de
manera que es fácil manejarlos teniendo presente que son considerados como
cadenas de caracteres, por lo que es probable que tengamos que realizar una
conversión de tipo para tratarlos correctamente.
Por ejemplo, si tenemos el archivo fibo.py con el siguiente contenido
42 Capítulo 3 Aspectos avanzados
run fibo.py 30
3 2 1 Salida formateada
La salida estándar (a pantalla) se realiza como ya hemos visto con la orden
print. Para impresiones sencillas nos bastará con concatenar adecuadamente
cadenas de caracteres:
x = 3; y = 4
print "El valor de 'x' es " + str(x) + " y el de 'y' es "
+ str(y)
0 0
1 1
4 8
9 27
16 64
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
En este caso, el contenido del interior de las llaves hace referencia a los
elementos del método format que le sigue, de manera que los números que
van antes de los dos puntos corresponden a los índices del objeto que sigue
a format y lo que va después de los dos puntos define el modo en el que se
imprimirán dichos objetos. Aquí van unos ejemplos:
abracadabra
alineación a izquierda
alineación a derecha
alineación centrada
2 2.000 2.00e+00
# coding: utf−8
print "Primera línea"
print "Segunda línea"
El método read del objeto archivo lee el archivo al que referencia el objeto
creado. Si se le proporciona un argumento numérico entonces lee un número
determinado de bytes del archivo;1 cuando es llamado sin argumento, lee el
archivo al completo. Cada llamada a read mueve el puntero de lectura del
archivo la último lugar leído, de manera que la llamada siguiente lee a partir
de ahí. Por eso:
f.read ()
1 Un byte puede considerarse un carácter, aunque hay caracteres que ocupan más de uno.
3.2 Entrada y salida de datos 45
''
produce una cadena vacía, pues el puntero se halla al final del archivo.
Podemos usar el método seek para situarnos en cualquier posición del
archivo.
f.seek (0) # Vamos al inicio del archivo
f.read ()
f.seek (0)
f. readline ()
print f. readline ()
f. readline ()
o con f.readlines() que almacena cada una de las líneas del archivo en una
lista:
f.seek (0)
for x in f. readlines ():
print x,
# coding: utf−8
print "Primera línea"
print "Segunda línea"
f.seek (0)
for x in f:
print x,
46 Capítulo 3 Aspectos avanzados
# coding: utf−8
print "Primera línea"
print "Segunda línea"
f.read ()
f. close ()
f = open('hola.py ','r+') # lectura y escritura
print f.read ()
primera
segunda
tercera
f. write('cuarta \n')
f.seek (0)
f. readlines ()
'segunda'
3.3 Más sobre estructuras de datos 47
'cuarta'
'cuarta'
También disponemos del método tell que nos indica con un entero la posición
en la que se encuentra el puntero del archivo.
La escritura con write también se puede hacer en pantalla si la usamos
como un objeto tipo archivo con el atributo stdout del módulo sys:
import sys
g = sys. stdout
g. write('Hola mundo\n')
Hola mundo
lo que puede ser útil para programar las salidas por pantalla durante la
elaboración de código con write, de modo que cuando queramos direccionar
la salida a un archivo sólo necesitamos cambiar la salida.
3 3
MÁS SOBRE ESTRUCTURAS DE DATOS
[0, 1, 4, 9, 16]
[[0, 0], [1, 1], [4, 8], [9, 27], [16, 64]]
a = range (10)
[x**3 for x in a if x %2 == 0] # cubo de los múltiplos de 2
48 Capítulo 3 Aspectos avanzados
[2, 4, 6]
[1, 3, 5]
una forma de escribir código que usa las características propias y peculiares del lenguaje
Python que auna sencillez, brevedad, elegancia y potencia.
3.3 Más sobre estructuras de datos 49
x = 5 # x apunta al objeto 5
id(x)
160714880
y = 5 # y apunta al objeto 5
id(y)
160714880
No hemos creado un nuevo objeto, sino una nueva referencia para el mismo
objeto, por lo que tienen el mismo identificador. Lo podemos comprobar con
la orden is:
x is y
True
x = x + 2 # x apunta al objeto 7
id(x)
160714856
id (7)
160714856
y ahora:
x is y
False
Con las listas pasa algo similar, salvo que ahora está permitido modificar
el objeto (porque son mutables), por lo que las referencias hechas al objeto
continuarán apuntado a él:
a = [1 ,2]
id(a) # identificador del objeto
3074955372L
[3, 2]
3074955372L
[0, 1, 2, 0, 1, 2]
Sin embargo,
x = x+[3] # nuevo objeto
y
[0, 1, 2, 0, 1, 2]
anterior, pero sí y. ¿Cómo podemos entonces copiar una lista? Podemos para
ello usar el slicing:
x = range (10)
y = x[:] # copiamos x a y
print id(x), id(y)
3074955372L 3075028972L
3 4
EXCEPCIONES
for a in [1 ,0]:
b = 1/a
print b
1
ZeroDivisionError: integer division or modulo by zero
Para evitarla, hacemos uso de las órdenes try y except del siguiente modo:
for a in [1 ,0]:
try:
b = 1/a
except :
print "Se ha producido un error "
b = 0
print b
1
Se ha producido un error
0
for a in [0,'1']:
try:
b = 1/a
except ZeroDivisionError :
print " División por cero"
b = 0
except TypeError :
print " División inválida "
b = 1
print b
3 5
EJERCICIOS
∑
100
1
E.1 Calcula √
i=1
i
E.2 Calcula la suma de los números pares entre 1 y 100.
E.3 Calcular la suma de todos los múltiplos de 3 o 5 que son menores que
1000. Por ejemplo, la suma de todos los múltiplos de 3 o 5 que son menores
que 10 es: 3 + 5 + 6 + 9 = 23
E.4 Utiliza la función randint del módulo random para crear una lista de
100 números aleatorios entre 1 y 10.
E.5 El Documento Nacional de Identidad en España es un número finalizado
con una letra, la cual se obtiene al calcular el resto de la división de dicho
número entre 23. La letra asignada al número se calcula según la siguiente
tabla:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
TRWAGMYFPD X B N J Z S Q V H L C K E
Escribe un programa que lea el número por teclado y muestre la letra asignada.
Por ejemplo, al número 28594978 le debe corresponder la letra K. Tres líneas
de código debería ser suficientes.
E.6 Usando un bucle while escribe un programa que pregunte por un
número por pantalla hasta que sea introducido un número impar múltiplo
de 3 y de 7 que sea mayor que 100.
E.7 Crea una lista aleatoria de números enteros (usar Ejercicio E.4) y luego
escribe un programa para que elimine los valores impares de dicha lista.
3.5 Ejercicios 53
E.8 Escribir una función histograma que admita una lista aleatoria de
números enteros entre 1 y 5 (usar Ejercicio E.4) y elabore un diagrama de
frecuencias de aparición de cada uno de los elementos de la lista según el
formato que sigue: por ejemplo, si la lista es
[1, 4, 2, 1, 4, 4, 5, 5, 5, 3]
(1,6)
(1,10)
E.10 Escribir una función que acepte como parámetros dos valores a y b, y
una función f tal que f (a)f (b) < 0 y que, mediante el método de bisección,
devuelva un cero de f . La aproximación buscada será controlada por un
parámetro ε que por defecto ha de ser 10−4 .
E.11 Considera la siguiente función:
def media (* valores ):
if len( valores ) == 0: # len = longitud de la tupla
return 0
else:
sum = 0
for x in valores :
sum += x
return sum / len( valores )
0
54 Capítulo 3 Aspectos avanzados
varios (1, 2)
1
2
varios (1, 2, 4, 3)
1
2
****
***
varios (3,4,a=1,b=3)
3
4
−
−−−
varios (2,5,1,a=2,b=3)
4 1
ARRAYS
import numpy as np
a = np.array ([1. ,3 ,6])
print a
[ 1. 3. 6.]
55
56 Capítulo 4 NumPy
type(a)
print a. dtype
<type 'numpy.ndarray'>
float64
int64
array([2, 3, 5])
Como el array es entero, todos los datos son convertidos a ese tipo. No
obstante, podemos cambiar de tipo todo el array,
a[0] = 3.6
print a
[ 3.6 3. 6. ]
dtype('float64')
4.1 Arrays 57
[[ 1. 3. 5.]
[ 2. 1. 8.]]
5.0 5.0
(2, 3)
2 in a # el elemento 2 está en a
True
4 in a # el elemento 4 no está en a
False
58 Capítulo 4 NumPy
4 2
FUNCIONES PARA CREAR Y MODIFICAR ARRAYS
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
array([2, 5, 8])
Nótese que todos los arrays creados son enteros. No obstante, esta orden
también admite parámetros reales
4 2 1 Modificación de forma
Con el método reshape podemos cambiar la forma de un array:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
o también,
array([[ 0, 3, 6, 9, 12],
[ 1, 4, 7, 10, 13],
[ 2, 5, 8, 11, 14]])
La opción por defecto equivale a order='C'. Las iniciales 'C' y 'F' correspon-
den a los lenguajes C y FORTRAN, respectivamente, y se refieren al modo
en el que estos lenguajes almacenan los datos multidimensionales.
El método transpose, que se puede abreviar como .T, en arrays bidimen-
sionales es equivalente a la transposición de matrices:
[[0 5]
[1 6]
[2 7]
[3 8]
[4 9]]
print a
[[0 1 2 3 4]
[5 6 7 8 9]]
[0 1 2 3 4 5 6 7 8 9]
60 Capítulo 4 NumPy
[0 5 1 6 2 7 3 8 4 9]
Nótese que todas estas funciones y métodos crean nuevos objetos, es decir, no
modifican los existentes.
Las siguientes funciones son útiles para crear arrays de un tamaño dado
(y reservar memoria en ese momento):
[ 0. 0. 0. 0. 0.]
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]
[[ 1. 1. 1. 1.]
[ 1. 1. 1. 1.]]
O bien
[[ 1. 0. 0.]
[ 0. 1. 0.]
[ 0. 0. 1.]]
[[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]]
o también
4.2 Funciones para crear y modificar arrays 61
[[ 0. 1. 0.]
[ 0. 0. 1.]
[ 0. 0. 0.]
[ 0. 0. 0.]]
[[ 0. 0. 0.]
[ 1. 0. 0.]
[ 0. 1. 0.]
[ 0. 0. 1.]]
[ 1. 1. 1.]
[[1 0 0]
[0 2 0]
[0 0 3]]
[[0 0 0]
[1 0 0]
[0 2 0]]
[[0 0 2 0]
[0 0 0 3]
[0 0 0 0]
[0 0 0 0]]
print np. random . randint (1 ,10 ,(2 ,2)) # array 2x2 de enteros
entre 1 y 9
[[1 3]
[8 4]]
4 3
SLICING
Al igual que con las listas, podemos acceder a los elementos de un array
mediante slicing, que en NumPy además admite más sofisticación. Por ejem-
plo, la asignación sobre un trozo de una lista funciona de diferente modo que
en los arrays:
a = range (5)
a [1:4] = [6] # eliminamos elementos en la lista
print a
[0, 6, 4]
[0 6 6 6 4]
[[0 1 2]
[3 4 5]
[6 7 8]]
[3 4 5]
[6 7 8]
[2 5 8]
a = range (5)
b = a # b es el mismo objeto
c = a[:] # c es un nuevo objeto
a[0] = -1 # modificamos a
b # se modifica
[−1, 1, 2, 3, 4]
c # no se modifica
[0, 1, 2, 3, 4]
[−1 10 2 3 4]
[[ 0 1 2]
[ 3 −1 5]
[ 6 7 8]]
[[−1 5]
[ 7 8]]
print a # no se ha modificado
[[0 1 2]
[3 4 5]
[6 7 8]]
4 4
OPERACIONES
print a+b
print a*b
print a/b
print b**a
la función dot.
a = np. arange (1. ,5). reshape (2 ,2)
b = np. arange (5. ,9). reshape (2 ,2)
print a
print b
[[ 1. 2.]
[ 3. 4.]]
[[ 5. 6.]
[ 7. 8.]]
[[ 5. 12.]
[ 21. 32.]]
[[ 19. 22.]
[ 43. 50.]]
[[ 0.84147098 0.90929743]
[ 0.14112001 −0.7568025 ]]
print np.exp(b)
[[ 148.4131591 403.42879349]
[ 1096.63315843 2980.95798704]]
import math
math.sin(a)
entonces, podemos usarla para trabajar sobre arrays del siguiente modo:
[0 1 2]
print a.T
[0 1 2]
print a. shape
(3,)
np.dot(a.T,a)
np.dot(a,a.T)
np.dot(a,a)
b = a. reshape (1 ,3)
print np.dot(b.T,b)
[[0 0 0]
[0 1 2]
[0 2 4]]
print np.dot(b,b.T)
o bien, de una forma un poco más sofisticada (pero más útil, pues no es
necesario conocer las dimensiones precisas para usar reshape), con la orden
newaxis, que crea una nueva dimensión en el array:
c = a[np. newaxis ]
print np.dot(c.T,c)
[[0 0 0]
[0 1 2]
[0 2 4]]
Obsérvese que
(1, 3)
[[0 0 0]
[0 1 2]
[0 2 4]]
[0 0 0]
4 4 1 Álgebra Lineal
[[ 1. 4. 4.]
[ 0. 0. 2.]
[ 2. 0. 0.]]
16.0
donde hay que tener en cuenta que los autovectores corresponden a las
columnas de vec.
Para el cálculo de la matriz inversa:
np. linalg .inv(a) # inversa
4.4 Operaciones 69
[[ 0. 0. 0.5 ]
[ 0.25 −0.5 −0.125]
[ 0. 0.5 0. ]]
[ 2. 3. 1.]
Comprobamos:
[ 0. 0. 0.]
4 4 2 Concatenación
[ 0 1 2 3 4 10 11 12 13 14]
[[ 0 1 2 3 4]
[10 11 12 13 14]]
Nótese la necesidad de añadir una dimensión extra para que se consideren los
arrays como vectores fila.
Para arrays multidimensionales:
70 Capítulo 4 NumPy
[[0 1 2]
[3 4 5]]
[[10 11 12]
[13 14 15]]
[[ 0 1 2]
[ 3 4 5]
[10 11 12]
[13 14 15]]
[[ 0 1 2 10 11 12]
[ 3 4 5 13 14 15]]
4 5
BROADCASTING
print a+1
[ 2. 3. 4.]
natural lo que se hace, se suma a cada elemento del array el escalar. Pero el
broadcasting en Python admite más sofisticación:
[[ 1. 2.]
[ 3. 4.]
[ 5. 6.]]
[−1. 3.]
print a+b
[[ 0. 5.]
[ 2. 7.]
[ 4. 9.]]
[[ 0. 1.]
[ 2. 3.]]
[ 1. 2.]
[[ 1. 3.]
[ 3. 5.]]
[[ 1. 2.]
[ 4. 5.]]
o alternativamente,
72 Capítulo 4 NumPy
[[ 1. 2.]
[ 4. 5.]]
(2, 2) (2,)
(2,2) (2, 1)
En este caso podemos calcular los productos matriciales AB y BA, con los
que obtenemos matrices 2 × 2 y 3 × 3, respectivamente:
4.5 Broadcasting 73
[[ 70 88]
[178 232]]
print np.dot(B,A)
[[ 30 42 54]
[ 62 90 118]
[ 94 138 182]]
Estas son las operaciones “lógicas” que se puede realizar con estas dos
matrices, pero podríamos pensar en alguna más. Por ejemplo, si consideramos
la primera columna de A y la primera fila de B, podríamos construir la matriz
2 × 2 obtenida al considerar el producto tensorial de vectores. Aunque este
producto tensorial se puede llevar a cabo mediante operaciones matriciales
como hicimos antes con dot o outer, el broadcasting también nos lo permite.
Por ejemplo,
[[ 2 4]
[14 28]]
[[ 2 4]
[14 28]]
[[18 24]
[54 72]]
[[ 50 60]
[110 132]]
74 Capítulo 4 NumPy
La ventaja que nos aporta NumPy es que es posible realizar esta misma
operación sin necesidad del bucle. Nótese que queremos multiplicar tres vec-
tores columna, por los correspondientes tres vectores filas. Esto es, vamos a
realizar 3 operaciones de vectores 2 × 1 con vectores 1 × 2. De este modo, de-
bemos considerar a A como 3 vectores columna (lo que corresponde a tamaño
(3,2,1))
[[[ 1]
[ 7]]
[[ 3]
[ 9]]
[[ 5]
[11]]]
(3, 2, 1)
[[[ 2 4]]
[[ 6 8]]
[[10 12]]]
(3, 1, 2)
Así,
4.6 Otros métodos de interés 75
[[[ 2 4]
[ 14 28]]
[[ 18 24]
[ 54 72]]
[[ 50 60]
[110 132]]]
4 6
OTROS MÉTODOS DE INTERÉS
[ 1 16 49 100 169]
335
13249600
169
0
76 Capítulo 4 NumPy
[10 16 49 50 50]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
a.sum ()
66
[12 15 18 21]
[ 6 22 38]
4 6 1 Comparaciones
También es interesante la comparación entre arrays:
a == b
a > 2
True
False
print a
[ 1. 3. 0.]
También existe la función where que crea un nuevo array a partir de una
comparación:
np. where(a!=0)
(array([0, 1, 3]),)
print np.sqrt(a)
[ nan 0. 1.]
4 7
INDEXACIÓN SOFISTICADA
Además del slicing que hemos visto, los arrays de NumPy se pueden
indexar a través de arrays con enteros o variables booleanas, denominados
máscaras. Veamos algunos ejemplos:
[11 9 12 15 11 7]
mask = (a %3 == 0) # múltiplos de 3
print mask
[ 9 12 15]
(array([1, 2, 3]),)
[11 −1 −1 −1 11 7]
[2 4 3 2 0]
[ 0.72321035 0. 0.76326975 0.
0.41174471 0.39349619
0.08833142]
[9 8 7 6 5 4 3 2 1 0]
80 Capítulo 4 NumPy
[[1 1]
[0 6]]
[[8 8]
[9 3]]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[ 8 11]
Si queremos acceder a las filas segunda y tercera, con las mismas columnas,
podemos usar el slicing:
print a[1:3 ,[0 ,3]]
[[ 4 7]
[ 8 11]]
[ 4 11]
[[ 4 7]
[ 8 11]]
4 8
OPERACIONES CON SLICING
4 9
LECTURA DE FICHEROS
[[ 2. 1.]
[ 4. 3.]
[ 6. 5.]
[ 8. 7.]
[ 10. 9.]]
4 10
BÚSQUEDA DE INFORMACIÓN
np.info(np.dot)
dot(a, b, out=None)
...
In file: /usr/local/lib/python2.7/dist−packages/numpy/
lib/twodim_base.py
"""
v = asarray(v)
s = v.shape
if len(s) == 1:
n = s[0]+abs(k)
res = zeros((n, n), v.dtype)
84 Capítulo 4 NumPy
if k >= 0:
i = k
else:
i = (−k) * n
res[:n−k].flat[i::n+1] = v
return res
elif len(s) == 2:
return v.diagonal(k)
else:
raise ValueError("Input must be 1− or 2−d.")
aunque es necesario advertir que puede que dicho código no esté disponible
para algunas funciones.
Por último, cuando no concemos el nombre exacto de la función, o su
posible existencia, podemos realizar una búsqueda por concepto para ver qué
funciones en NumPy están relacionadas con ese tema. Por ejemplo, si estamos
buscando algún tipo de descomposición matricial y queremos ver qué posee
NumPy, podemos usar la función lookfor:
numpy.polynomial.Chebyshev.fit
Least squares fit to data.
numpy.polynomial.Polynomial.fit
Least squares fit to data.
numpy.polynomial.hermite.hermfit
Least squares fit of Hermite series to data.
numpy.polynomial.laguerre.lagfit
Least squares fit of Laguerre series to data.
numpy.polynomial.legendre.legfit
Least squares fit of Legendre series to data.
numpy.polynomial.chebyshev.chebfit
Least squares fit of Chebyshev series to data.
numpy.polynomial.hermite_e.hermefit
Least squares fit of Hermite series to data.
numpy.polynomial.polynomial.polyfit
Least−squares fit of a polynomial to data.
4 11
EJERCICIOS
E.2 Escribe una función tenga como argumento de entrada una matriz y
devuelva 1 si es simétrica, −1 si es antisimétrica y 0 en caso contrario.
E.3 Crear una función para construir una matriz de tamaño n con una
estructura como la siguiente:
2 −1 0 0 ··· 0 0
−1 2 −1 0 ··· 0 0
.. .. .. .. .. .. ..
. . . . . . .
0 0 0 0 ··· 2 −1
0 0 0 0 ··· −1 2
E.10 Crear una función para construir una matriz de tamaño n con una
estructura como la siguiente:
1 2 3 ··· n−1 n
1 3 3 ··· n−1 n
1 2 5 ··· n−1 n
. . . ..
. . . .. ..
. . . . . .
1 2 3 ··· 2n − 3 n
1 2 3 ··· n − 1 2n − 1
E.13 Construye una función para calcular, en función del tamaño, los
autovalores de las matrices del tipo siguiente y comprueba que su producto
88 Capítulo 4 NumPy
E.14 Construye una función tal que, dado un array de longitud cualquiera,
construya el conocido como determinante de Vandermonde.
1 1 1 ··· 1
x1 x2 x3 ··· xn
x2 x22 x23 ··· x2n
1
. .. .. ..
. ..
. . . . .
xn−1 xn−1 xn−1 · · · xn−1
1 2 3 n
¿Podrías escribir el código para calcular esta fórmula usando un solo bucle?
¿Y sin bucles?
E.15 Crea un array aleatorio de enteros entre 0 y 100 bidimensional, de
tamaño 1000 × 1000. Cuenta el número de múltiplos de 5 que hay en cada fila
y luego calcula la media de los valores obtenidos. Repite el proceso 100 veces.
Indicación: usa el método mean.
E.16 Considera un conjunto de n puntos uniformemente espaciados en el
intervalo (0, 1), x0 < x1 < · · · < xn−1 . Dada una función u, sabemos que una
aproximación de la derivada segunda en un punto x viene dada por
5 1
OPTIMIZACIÓN SIN RESTRICCIONES
Submódulo Descripción
cluster Algoritmos de agrupamiento
constants Constantes físicas y matemáticas
fftpack Rutinas para la Transformada Rápida de Fourier
integrate Integración de ecuaciones diferenciales ordinarias
interpolate Interpolación y splines regulares
io Entrada y salida de datos
linalg Álgebra lineal
ndimage Procesamiento de imágenes
odr Regresión ortogonal
optimize Optimización y cálculo de raíces
signal Procesamiento de señales
sparse Matrices dispersas
spatial Estructuras de datos espaciales
special Funciones especiales
stats Funciones estadísticas
weave Integración con C/C++
∑ −1
N
[ ]
f (x0 , . . . , xN −1 ) = 100(xi − x2i−1 )2 + (1 − xi−1 )2
i=1
siendo el resultado:
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 26
Function evaluations: 2870
resultando:
direc: array([[ 1.00000000e+00, 0.00000000e+00,
0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 0.00000000
e+00,
0.00000000e+00],
[ −1.16176646e−06, −1.38842362e−06, 5.31922868
e−06,
1.18136018e−05, 4.32075655e−06, −1.96558476
e−06,
9.91332650e−06],
[ 1.87538194e−08, 4.17940823e−08, 6.17951780
e−07,
6.04908798e−07, 9.14032521e−07, 1.69204568
e−06,
2.60026901e−06],
94 Capítulo 5 SciPy
print opt.x
[ 1. 1. 1. 1. 1. 1. 1.]
∂f
= −400x0 (x1 − x20 ) − 2(1 − x0 )
∂x0
∂f
= 200(xj − x2j−1 ) − 400xj (xj+1 − x2j ) − 2(1 − xj ), 1 ≤ j ≤ N − 2
∂xj
∂f
= 200(xN −1 − x2N −2 )
∂xN −1
# óptimo :
print opt1.x
# óptimo :
print opt2.x
# óptimo
print opt3.x
5 2
OPTIMIZACIÓN CON RESTRICCIONES
Minimizar f (x)
sujeto a hi (x) = 0, 1 ≤ i ≤ n,
gj (x) ≥ 0, 1 ≤ j ≤ m,
lk ≤ x k ≤ u k , 1 ≤ k ≤ N,
def fobj(x):
return x [0]**2 + 2*x [1]**2 - 2*x[0]*x[1] - 2*x[0]
constr1 = {'type ':'eq ', 'fun ': lambda x: x[0]**3 -x[1], '
jac ': lambda x: np.array ([3*x[0]**2 , -1.])}
constr2 = {'type ':'ineq ', 'fun ': lambda x: x[1]-1 , 'jac ':
lambda x: np.array ([0. ,1.])}
constr = (constr1 , constr2 )
print res
fun: −1.0000001831052137
jac: array([−1.99999982, 1.99999982, 0. ])
message: 'Optimization terminated successfully.'
nfev: 14
nit: 9
njev: 9
status: 0
success: True
x: array([ 1.00000009, 1. ])
5.3 Interpolación de datos 99
5 3
INTERPOLACIÓN DE DATOS
(0.00, 0.00), (0.20, 0.56), (0.40, 0.93), (0.60, 0.97), (0.80, 0.68), (1.00, 0.14)
f = interp1d (x,y)
print f(x)
print f (0.23)
0.6155
5 4 3 2
−1.563 x + 6.771 x − 9.479 x + 1.604 x + 2.807 x
5.4 Resolución de ecuaciones diferenciales 101
5 4
RESOLUCIÓN DE ECUACIONES DIFERENCIALES
y ′′ + γy ′ + ωy = 0
omega = 2.
gamma = 0.5
y0 = [2.5 , 0] # condiciones iniciales
5 5
EJERCICIOS
Maximizar xexy
sujeto a x2 + y = 0
y ′′ − xy = 0
1 1
y(0) = √ , y ′ (0) = − √
3
32 Γ( 23 )
3
3Γ( 13 )
5.5 Ejercicios 103
El Backend
105
106 Capítulo 6 Gráficos con Matplotlib
mientras que si queremos que los gráficos aparezcan en una ventana propia
bastará poner
%matplotlib
que nos informa del backend seleccionado. Para manejar gráficos de forma
interactiva sugerimos usar esta segunda opción.
6 1
GRÁFICOS INTERACTIVOS
6 1 1 Interactividad
Una vez cargado el módulo pylab, lo primero que haremos será saber si la
sesión es o no interactiva, para lo cual usamos la función:
True
figure ()
<matplotlib.figure.Figure at 0x7f83db020290>
6 1 2 Figuras y gráficos
La orden figure() crea una ventana con título Figure más un número
entero que irá incrementándose sucesivamente. Es posible hacer la llamada
de la forma figure(num), bien para crear la figura con la numeración que
deseemos, o bien, si dicha figura existe, para hacerla activa. En lugar de un
número entero es posible pasar un string como argumento, que se convertirá
en el título de la ventana creada.
La orden
plot ([1 ,3 ,2])
los puntos de abscisa dada por el índice de la lista, y ordenada dada por el
valor de la lista. En el caso de la Figura 6.2, se crea una línea que une los
puntos (0, 1), (1, 3) y (2, 2).
El resultado puede verse en la Figura 6.3. Nótese que hemos usado la función
arange de NumPy (recuérdese que pylab importa éste módulo) y que por
tanto, x e y son arrays. Obsérvese también cómo el gráfico es reescalado para
poder mostrar la nueva línea en el eje que ya estaba creado.
Podríamos haber hecho que el nuevo comando plot borrara el dibujo
anterior, en lugar de añadirse al existente. La función hold es la encargada de
activar o desactivar el estado de concurrencia, esto es, si los sucesivos dibujos
se mostrarán junto a los anteriores, o bien éstos serán borrados y sustituidos
por el último. Se puede cambiar de estado invocándola sin parámetro, o bien
6.1 Gráficos interactivos 109
Si lo que queremos es borrar los gráficos de la figura activa sin cerrar la ventana
disponemos de
6 1 3 Subplots
El posible tener varios ejes distintos en la misma ventana gráfica, para lo
cual usaremos la orden:
subplot (n,m,k)
subplot (234)
110 Capítulo 6 Gráficos con Matplotlib
abre una ventana como la de la Figura 6.4a y selecciona dicho eje como el
eje activo. Nótese que la figura es dividida en dos filas de tres columnas cada
(a) (b)
bujará el gráfico correspondiente sobre el eje activo. Por ejemplo, la Figura 6.6
corresponde a las siguientes órdenes:
subplot (221)
subplot (222)
subplot (212)
x = linspace (0 ,1 ,10)
y = sin(x)
z = cos(x)
w = sqrt(x)
plot(x,w) # dibuja sobre el eje activo (212)
subplot (221) # nuevo eje activo (221)
plot(x,y) # dibuja sobre el eje activo (221)
subplot (222) # cambiamos de eje activo al (222)
plot(x,z) # dibuja sobre el eje activo (222)
6 1 4 Axes
crea unos ejes por defecto, que equivale a hacer subplot(111). Si a continuación
escribimos:
axes ([0.2 ,0.5 ,0.3 ,0.3])
6 2
AÑADIENDO OPCIONES
normalizadas [0.125,0.1,0.775,0.8].
6.2 Añadiendo opciones 113
x = linspace (0 ,1 ,30)
y = sqrt(x)
z = x**2
(a) plot(x,y,'r-o',x,z,'g:')
(b) plot(x,y,'m--s',x,z,'bx')
comando plot.
Además de este tipo de opciones abreviadas, el comando plot permite con-
figurar muchos otros aspectos del gráfico a través de argumentos opcionales,
algunos de los cuales tienen el mismo efecto que los ya vistos. Puesto que no es
nuestra intención ser exhaustivos, mostraremos algunos ejemplos de opciones
en la siguiente sección a la vez que introducimos algo más de control sobre los
gráficos.
6 3
CONFIGURANDO VARIOS ELEMENTOS DEL GRÁFICO
Títulos y leyendas
Podemos incluir un título al eje del gráfico a dibujar con el comando
title (cadena)
También es posible distinguir cada uno de las líneas trazadas con plot
mediante una leyenda, usando una etiqueta definida por el argumento opcional
6.3 Configurando varios elementos del gráfico 115
label. La leyenda se activa con el comando legend, que entre otros argumentos
permite situar la leyenda en posiciones predeterminadas con la opción loc, el
estilo de fuente, etc. Una vez más la ayuda del comando proporciona todas
las posibilidades. La Figura 6.9 muestra el resultado de las siguientes órdenes:
x = linspace (0 ,1 ,20)
y = x**2
z = x**3
plot(x,y, linewidth =2, label='$x ^2$',color =(0 ,1 ,0))
plot(x,z, linestyle ='dashed ',color =(1 ,0 ,1) ,label ='$x ^3$')
title ('Un par de funciones ',fontsize =14)
legend (loc =0)
Nótese que en las cadenas de caracteres que conforman las etiquetas para la
leyenda se ha usado notación LATEX. También se han usado otras opciones del
comando plot. La leyenda debe ser activada después de los comandos plot y
recogerá todas las etiquetas en función del orden.
Texto y anotaciones
La Figura 6.10 ha sido generada con el siguiente código:
origen del vector, y las dos segundas las coordenadas del desplazamiento (que
no las coordenadas del extremo). Las opciones empleadas son autoexplicativas.
6 4
GRÁFICOS Y OBJETOS
Crearemos una figura, la cual asignamos a una variable para acceder adecua-
damente a los métodos disponibles.
Los objetos gráficos tienen su propia jerarquía, por ejemplo, en una figura
podemos incluir varios ejes (tal y como hacíamos con subplot):
que se use en el ejemplo, pues en ocasiones algunas características no están cubiertas por
versiones inferiores.
6.4 Gráficos y objetos 119
Ahora la variable a es una lista que contiene dos objetos gráficos de tipo
Line2D, y b es un sólo objeto gráfico de este tipo. Obsérvese el uso de la coma
para almacenar el objeto gráfico y no la lista.5 Ahora podemos acceder a las
diversas propiedades de cada uno de los objetos gráficos usando métodos:
El resultado puede verse en la Figura 6.12. Las distintas opciones para el objeto
Line2D pueden consultarse en la ayuda. Por supuesto, también se pueden
emplear las opciones del mismo modo que en la secciones anteriores.
Para tratar distintos elementos de un gráfico, también es posible usar la
función setp que asigna una (o varias) propiedades a un objeto. Por ejemplo,
haría que las dos curvas de eje superior tengan ambas grosor 3, y que el eje
inferior luzca un título. Las mismas propiedades que hemos modificado en los
ejemplos anteriores pueden modificarse con esta orden.
Figura 6.12
# banda de resaltado
band = ax. axvspan (2* np.pi /5 ,3* np.pi /5)
band. set_color ('red ') # ponemos color
band. set_alpha (0.2) # ponemos transparencia
6.5 Gráficos 3D 121
Vemos ahora que la celda de salida está ocupada por el gráfico de la Figu-
ra 6.13.
La función axis muestra y/o establece las propiedades de los ejes. En
concreto, el argumento 'tight' hace que los ejes se ajusten a los datos del
gráfico. Otras posibilidades son 'off', 'equal' o 'scaled'.
La orden grid activa o desactiva (con True o False, respectivamente) la
malla que puede verse de fondo en el gráfico.
Es posible especificar, no sólo dónde se sitúan las marcas de los ejes, sino
también, la etiqueta que lleva cada una. En este ejemplo se ha hecho de forma
diferente para cada eje. Con la función xticks, que admite una o dos listas,
señalamos la posición de las marcas con la primera lista, y, si existe, la cadena
de caracteres que se imprimirá en cada etiqueta con la segunda. Nótese el uso
de notación LATEX.
En el eje Y hemos determinado las marcas mediante el método set_yticks
y las etiquetas con set_yticklabels. Esta segunda opción nos permite además
especificar color, tamaño de fuente o rotación, entre otras propiedades.
Además hemos añadido un nuevo objeto en el gráfico, una banda vertical
de resaltado con la función axvspan, a la que hemos modificado el color y la
transparencia con los métodos adecuados.
Finalmente, podemos salvar el fichero gráfico a disco con la función
para la que basta precisar el nombre del fichero a guardar y el formato del
mismo.6 Para otras opciones, consultar la ayuda.
6 5
GRÁFICOS 3D
6 También podemos salvar los gráficos tanto desde la ventana gráfica como desde el gráfico
Figura 6.13
Podemos dibujar curvas con el método plot vinculado a este tipo de ejes,
usando tres listas o arreglos que proporcionan las coordenadas de los puntos
de la curva. Por ejemplo,
( √ )
f (x, y) = sin 2π x2 + y 2
El parámetro zdir señala el eje sobre el que se dibujan los contornos, mientras
124 Capítulo 6 Gráficos con Matplotlib
que offset señala el nivel en el que se muestran (si este parámetro no aparece,
se dibuja cada contorno en su nivel correspondiente). Nótese la selección de
transparencia sobre el objeto cset con el parámetro alpha y el comando setp.
6 6
EJERCICIOS
E.6 Considera los puntos (0, 0), (1, 3), (2, −1), (3, 2), (4, 2) y, (5, −1).
Dibújalos usando triángulos de color verde. A continuación, calcula la función
interpoladora lineal, el spline cúbico y el polinomio interpolador de Lagrange.
Dibuja cada uno de ellos en un color distinto y etiquétalos para que aparezca
una leyenda.
126 Capítulo 6 Gráficos con Matplotlib
(c) 100 ptos. en el círculo unida�d (d) 100 ptos. en el círculo unidad
129
130 Capítulo 7 Programación Orientada a Objetos
5
2 3
3
1 4
2
0 1
0
Supongamos ahora que queremos crear una estructura de barras con una
configuración regular como la de la Figura 7.1. No es difícil construir una
función para obtener los arrays de coordenadas y conexiones para una estruc-
tura de este tipo. Típicamente se construiría una función cuyos parámetros
de entrada fueran el número de nodos que vamos a tener en cada dimensión y
cuya salida fueran los arrays de coordenadas y conexiones correspondientes.
No obstante, vamos a crear esta estructura mediante objetos. Inicialmente
podrá parecer que es más complicado proceder de este modo, pero más
adelante veremos que merece la pena diseñar la estructura así, pues nos
facilitará la implementación de nuevas posibilidades.
7 1
DEFINIENDO CLASES
Las clases se definen con la palabra clave class seguida del nombre asigna-
do a la clase y que define el tipo de objeto, y como parámetros, los objetos de
los cuales hereda (veremos el concepto de herencia un poco más abajo).2 Es
una convención ampliamente usada nombrar las clases definidas por el usua-
rio con la inicial en mayúsculas. También es muy conveniente documentar
adecuadamente la clase.
Como es habitual en Python, la sangría marcará el fragmento de código
correspondiente a la clase. A continuación, aunque en Python no es obliga-
torio, aparece el denominado constructor. Se trata del método __init__ que
se ejecuta cuando la clase se instancia. El proceso de instanciación no es más
que la definición de un objeto perteneciente a esta clase.
Puesto que __init__ es un método, esto es, una función, se define como ya
vimos con la palabra clave def. Los argumentos de los métodos de una clase
son un poco peculiares pues el primero de ellos siempre es self, que se refiere
al propio objeto.3 El resto de argumentos deberá aparecer en el momento de
instanciar al objeto, y los podemos entender como los argumentos de entrada
en la creación del objeto.
De este modo, para definir un objeto punto, instanciamos su clase del
siguiente modo:
En principio no hay mucho más que hacer con un objeto de este tipo. Podemos
acceder a sus atributos o bien modificarlos:
p.x
2.0
p.y
2 Por defecto, las clases se definen a través de la herencia con la clase object.
3 Esto es un convenio universalmente aceptado pero podría usarse cualquier otro nombre.
132 Capítulo 7 Programación Orientada a Objetos
3.0
p.x = 5.
print p
(2.0,3.0)
Entonces,
print a.p
(1.0,3.0)
7.1 Definiendo clases 133
b.p.x
1.0
Sin embargo, dado que hay una gran similitud entre los objetos tipo punto
y los objetos tipo nodo, otra opción consiste en apoyarse en el concepto de
herencia, que no es más que el establecimiento de una relación entre dos
clases, de manera que los atributos y métodos de una puedan ser usados en
la otra. En nuestro caso es evidente que los atributos x e y de la clase Point
deberán mantenerse en la nueva clase que vamos a crear, por lo que podemos
aprovecharnos del constructor de la clase Point usando el comando super:
(1.0,2.0)
a.id
b.id
1
134 Capítulo 7 Programación Orientada a Objetos
Nótese que para la impresión del objeto Node se está usando el método __str__
de la clase Point. Si quisiéramos una impresión distinta habría que definir
nuevamente el método __str__ para esta clase.
Ahora no debe ser difícil para el lector entender la clase para las barras
siguiente:
class Bar( object ):
"""
define una barra soportada por dos nodos
"""
def __init__ (self ,n1 ,n2):
if n1.id == n2.id:
print "Error: no hay barra "
return
elif n1.id < n2.id:
self.orig = n1
self.fin = n2
else:
self.orig = n2
self.fin = n1
def __str__ (self):
return " Barra de extremos los nodos {0} y {1}".
format (self.orig.id ,self.fin.id)
Node. numberNode = 0
# construcción de nodos
nodx = np. linspace (p1.x,p2.x,nx +1)
nody = np. linspace (p1.y,p2.y,ny +1)
for yy in nody:
for xx in nodx:
self.nodos. append (Node(xx ,yy))
# construcción de barras
for j in range (ny):
for i in range (nx):
n1 = i+ j*(nx +1)
n2 = n1 + 1
n3 = n1 + nx + 1
n4 = n3 + 1
# barras en cada elemento
b1 = Bar(self.nodos[n1],self.nodos[n2])
b2 = Bar(self.nodos[n1],self.nodos[n3])
b3 = Bar(self.nodos[n1],self.nodos[n4])
b4 = Bar(self.nodos[n2],self.nodos[n3])
self. barras . extend ([b1 ,b2 ,b3 ,b4])
# barras finales a la derecha
self. barras . append (Bar(self.nodos [n2],self.
nodos[n4]))
Nótese que hemos definido un par de listas: nodos y barras en las que almace-
nar los elementos que nos interesan. Ponemos el contador del identificador de
nodos a cero, de manera que cada vez que tengamos una estructura, los nodos
se creen comenzando con el identificador en 0. Tal y como está construido, el
identificador de cada nodo coincide con el índice que ocupa en la lista nodos,
lo que nos simplifica la búsqueda de los nodos.
Para obtener los nodos y las barras disponemos de las listas anteriores,
pero será más cómodo si definimos unos métodos que nos proporcionen di-
rectamente la información que realmente queríamos precisar de la estructura,
esto es, las coordenadas de los nodos y los índices correspondientes a cada
barra.
Por ello, a la clase anterior le añadimos los siguientes métodos:
m. get_connection ()
7.1 Definiendo clases 137
array([[0, 1],
[0, 2],
[0, 3],
[1, 2],
[1, 3],
[2, 3]])
Es evidente que podríamos haber creado una función que tuviera como
entrada las coordenadas de los puntos del rectángulo y el número de nodos a
usar en cada dimensión, y cuya salida fuera precisamente los dos arrays que
hemos obtenido; posiblemente hubiera sido incluso más sencillo de implemen-
tar. Sin embargo, como ahora veremos, es más conveniente el uso de clases
porque nos va a permitir una flexibilidad aun mayor.
7 1 1 Modificando clases
De este modo, una vez creada una estructura, nos bastará con invocar al
método plotting para obtener el gráfico correspondiente.
138 Capítulo 7 Programación Orientada a Objetos
7 2
CONTROLANDO ENTRADAS Y SALIDAS
A = np.array
([[10 , -1 ,2 ,0.] ,[ -1 ,11 , -1 ,3] ,[2 , -1 ,10 , -1] ,[0 ,3 , -1 ,8]])
b = np.array ([6. ,25 , -11 ,15])
iterativo (A,b)
Iteraciones realizadas: 23
array([ 1., 2., −1., 1.])
Iteraciones realizadas: 10
array([ 1., 2., −1., 1.])
a.k
23
a. metodo = seidel
a. iteracion ()
a.k
10
a.eps =1.e -4
a. iteracion ()
a.k
jacobi
Precisión: 1e−02 −−− Iteraciones: 7
Precisión: 1e−04 −−− Iteraciones: 12
Precisión: 1e−06 −−− Iteraciones: 18
Precisión: 1e−08 −−− Iteraciones: 23
Precisión: 1e−10 −−− Iteraciones: 28
Precisión: 1e−12 −−− Iteraciones: 34
seidel
Precisión: 1e−02 −−− Iteraciones: 3
Precisión: 1e−04 −−− Iteraciones: 6
Precisión: 1e−06 −−− Iteraciones: 8
Precisión: 1e−08 −−− Iteraciones: 10
Precisión: 1e−10 −−− Iteraciones: 11
Precisión: 1e−12 −−− Iteraciones: 13
7 3
EJERCICIOS
E.2 Para la clase Truss de la sección 7.1, escribir un método para que el
comando print proporcione información sobre el número de nodos y el número
de barras de la estructura.
E.3 Define una clase que contenga dos métodos: getString con el que
obtener una cadena de texto introducida por teclado y printString que
imprima la cadena obtenida en mayúsculas, dejando un espacio de separación
entre cada letra. Debería funcionar del siguiente modo:
a = InputOutString ()
a. getString ()
a. printString ()
H O L A