Tutorial Python 3.5.1 Completo
Tutorial Python 3.5.1 Completo
Introduccin
Python es un lenguaje de programacin poderoso y fcil de aprender. Cuenta con estructuras de datos eficientes y de
alto nivel y un enfoque simple pero efectivo a la programacin orientada a objetos. La elegante sintaxis de Python y su
tipado dinmico, junto con su naturaleza interpretada, hacen de ste un lenguaje ideal para scripting y desarrollo
rpido de aplicaciones en diversas reas y sobre la mayora de las plataformas.
El intrprete de Python y la extensa biblioteca estndar estn a libre disposicin en forma binaria y de cdigo fuente
para las principales plataformas desde el sitio web de Python, https://www.python.org/, y puede distribuirse libremente.
El mismo sitio contiene tambin distribuciones y enlaces de muchos mdulos libres de Python de terceros, programas
y herramientas, y documentacin adicional.
El intrprete de Python puede extenderse fcilmente con nuevas funcionalidades y tipos de datos implementados en C
o C++ (u otros lenguajes accesibles desde C). Python tambin puede usarse como un lenguaje de extensiones para
aplicaciones personalizables.
Este tutorial introduce de manera informal al lector a los conceptos y caractersticas bsicas del lenguaje y el sistema
de Python. Es bueno tener un interprete de Python a mano para experimentar, sin embargo todos los ejemplos estn
aislados, por lo tanto el tutorial puede leerse estando desconectado.
Para una descripcin de los objetos y mdulos estndar, mir La referencia de la biblioteca. La referencia de la
biblioteca provee una definicin ms formal del lenguaje. Para escribir extensiones en C o C++, le Extendiendo e
Integrando el Intrprete de Python y la Referencia de la API Python/C. Hay tambin numerosos libros que tratan a
Python en profundidad.
Este tutorial no pretende ser exhaustivo ni tratar cada una de las caractersticas, o siquiera las caractersticas ms
usadas. En cambio, introduce la mayora de las caractersticas ms notables de Python, y te dar una buena idea del
gusto y estilo del lenguaje. Luego de leerlo, sers capaz de leer y escribir mdulos y programas en Python, y estars
listo para aprender ms de los variados mdulos de la biblioteca de Python descriptos en La referencia de la
biblioteca.
Tambin vale la pena mirar el glosario.
2. Abriendo tu apetito
Si trabajs mucho con computadoras, eventualmente encontrars que te gustara automatizar alguna tarea. Por
ejemplo, podras desear realizar una bsqueda y reemplazo en un gran nmero de archivos de texto, o renombrar y
reorganizar un montn de archivos con fotos de una manera compleja. Tal vez quieras escribir alguna pequea base
de datos personalizada, o una aplicacin especializada con interfaz grfica, o un juego simple.
Si sos un desarrollador de software profesional, tal vez necesites trabajar con varias bibliotecas de C/C++/Java pero
encuentres que se hace lento el ciclo usual de escribir/compilar/testear/recompilar. Tal vez ests escribiendo una
batera de pruebas para una de esas bibliotecas y encuentres que escribir el cdigo de testeo se hace una tarea
tediosa. O tal vez has escrito un programa al que le vendra bien un lenguaje de extensin, y no quieres
disear/implementar todo un nuevo lenguaje para tu aplicacin.
Python es el lenguaje justo para ti.
Podras escribir un script (o programa) en el interprete de comandos o un archivo por lotes de Windows para algunas
de estas tareas, pero los scripts se lucen para mover archivos de un lado a otro y para modificar datos de texto, no
para aplicaciones con interfaz de usuario o juegos. Podras escribir un programa en C/C++/Java, pero puede tomar
mucho tiempo de desarrollo obtener al menos un primer borrador del programa. Python es ms fcil de usar, est
disponible para sistemas operativos Windows, Mac OS X y Unix, y te ayudar a realizar tu tarea ms velozmente.
Python es fcil de usar, pero es un lenguaje de programacin de verdad, ofreciendo mucha ms estructura y soporte
para programas grandes de lo que pueden ofrecer los scripts de Unix o archivos por lotes. Por otro lado, Python
ofrece mucho ms chequeo de error que C, y siendo un lenguaje de muy alto nivel, tiene tipos de datos de alto nivel
incorporados como arreglos de tamao flexible y diccionarios. Debido a sus tipos de datos ms generales Python
puede aplicarse a un dominio de problemas mayor que Awk o incluso Perl, y an as muchas cosas siguen siendo al
menos igual de fcil en Python que en esos lenguajes.
Python te permite separar tu programa en mdulos que pueden reusarse en otros programas en Python. Viene con
una gran coleccin de mdulos estndar que puedes usar como base de tus programas, o como ejemplos para
empezar a aprender a programar en Python. Algunos de estos mdulos proveen cosas como entrada/salida a
archivos, llamadas al sistema, sockets, e incluso interfaces a sistemas de interfaz grfica de usuario como Tk.
Python es un lenguaje interpretado, lo cual puede ahorrarte mucho tiempo durante el desarrollo ya que no es
necesario compilar ni enlazar. El intrprete puede usarse interactivamente, lo que facilita experimentar con
caractersticas del lenguaje, escribir programas descartables, o probar funciones cuando se hace desarrollo de
programas de abajo hacia arriba. Es tambin una calculadora de escritorio prctica.
Python permite escribir programas compactos y legibles. Los programas en Python son tpicamente ms cortos que
sus programas equivalentes en C, C++ o Java por varios motivos:
los tipos de datos de alto nivel permiten expresar operaciones complejas en una sola instruccin
la agrupacin de instrucciones se hace por sangra en vez de llaves de apertura y cierre
no es necesario declarar variables ni argumentos.
Python es extensible: si ya sabes programar en C es fcil agregar una nueva funcin o mdulo al intrprete, ya sea
para realizar operaciones crticas a velocidad mxima, o para enlazar programas Python con bibliotecas que tal vez
slo estn disponibles en forma binaria (por ejemplo bibliotecas grficas especficas de un fabricante). Una vez que
ests realmente entusiasmado, pods enlazar el intrprete Python en una aplicacin hecha en C y usarlo como
lenguaje de extensin o de comando para esa aplicacin.
Por cierto, el lenguaje recibe su nombre del programa de televisin de la BBC Monty Pythons Flying Circus y no
tiene nada que ver con reptiles. Hacer referencias a sketches de Monty Python en la documentacin no slo esta
permitido, sino que tambin est bien visto!
Ahora que ya ests emocionado con Python, querrs verlo en ms detalle. Como la mejor forma de aprender un
lenguaje es usarlo, el tutorial te invita a que juegues con el intrprete de Python a medida que vas leyendo.
En el prximo captulo se explicar la mecnica de uso del intrprete. Esta es informacin bastante mundana, pero es
esencial para poder probar los ejemplos que aparecern ms adelante.
El resto del tutorial introduce varias caractersticas del lenguaje y el sistema Python a travs de ejemplos, empezando
con expresiones, instrucciones y tipos de datos simples, pasando por funciones y mdulos, y finalmente tocando
conceptos avanzados como excepciones y clases definidas por el usuario.
...en la terminal. [1] Ya que la eleccin del directorio dnde vivir el intrprete es una opcin del proceso de instalacin,
puede estar en otros lugares; consult a tu Gur Python local o administrador de sistemas. (Por
ejemplo, /usr/local/python es una alternativa popular).
En mquinas con Windows, la instalacin de Python por lo general se encuentra en C:\Python35, aunque se puede
cambiar durante la instalacin. Para aadir este directorio al camino, podes ingresar la siguiente orden en el prompt
de DOS:
set path=%path%;C:\python35
Se puede salir del intrprete con estado de salida cero ingresando el carcter de fin de archivo (Control-D en
Unix, Control-Z en Windows) en el prompt primario. Si esto no funciona, se puede salir del intrprete
ingresando: quit().
Las caractersticas para editar lneas del intrprete incluyen edicin interactiva, sustitucin usando el historial y
completado de cdigo en sistemas que soportan readline. Tal vez la forma ms rpida de detectar si las
caractersticas de edicin estn presentes es ingresar Control-P en el primer prompt de Python que aparezca. Si se
escucha un beep, las caractersticas estn presentes; ver Apndice Edicin de entrada interactiva y sustitucin de
historial para una introduccin a las teclas. Si no pasa nada, o si aparece ^P, estas caractersticas no estn
disponibles; solo vas a poder usar backspace para borrar los caracteres de la lnea actual.
La forma de operar del intrprete es parecida a la lnea de comandos de Unix: cuando se la llama con la entrada
estndar conectada a una terminal lee y ejecuta comandos en forma interactiva; cuando es llamada con un nombre de
archivo como argumento o con un archivo como entrada estndar, lee y ejecuta un script del archivo.
Una segunda forma de iniciar el intrprete es python -c comando [arg] ..., que ejecuta las sentencias en comando,
similar a la opcin -c de la lnea de comandos. Ya que las sentencias de Python suelen tener espacios en blanco u
otros caracteres que son especiales en la lnea de comandos, es normalmente recomendado citar comando entre
comillas dobles.
Algunos mdulos de Python son tambin tiles como scripts. Pueden invocarse usando python -m module [arg] ...,
que ejecuta el cdigo demodule como si se hubiese ingresado su nombre completo en la lnea de comandos.
Cuando se usa un script, a veces es til correr primero el script y luego entrar al modo interactivo. Esto se puede
hacer pasndole la opcin -i antes del nombre del script.
Todas las opciones de lnea de comandos estn se descriptas en Lnea de comandos y entorno.
estndar), sys.argv[0] vale '-'. Cuando se usa -c command, sys.argv[0] vale '-c'. Cuando se usa m module, sys.argv[0] toma el valor del nombre completo del mdulo. Las opciones encontradas luego de c command o -m module no son consumidas por el procesador de opciones de Python pero de todas formas
almacenadas en sys.argv para ser manejadas por el comando o mdulo.
Las lneas de continuacin son necesarias cuando queremos ingresar un constructor multilnea. Como en el ejemplo,
mir la sentencia if:
>>> el_mundo_es_plano = True
>>> if el_mundo_es_plano:
...
...
Ten cuidado de no caerte!
Con esa declaracin, todo en el archivo fuente ser tratado utilizando la codificacin encoding en lugar de UTF-8. La
lista de posibles codificaciones se puede encontrar en la Referencia de la Biblioteca de Python, en la seccin
sobre codecs.
Por ejemplo, si tu editor no soporta la codificacin UTF-8 e insiste en usar alguna otra, digamos Windows-1252, pods
escribir:
# -*- coding: cp-1252 -*-
y usar todos los caracteres del conjunto de Windows-1252 en los archivos fuente. El comentario especial de la
codificacin debe estar en la primera o segunda linea del archivo.
Footnotes
[1]
En Unix, el intrprete de Python 3.x no se instala por default con el ejecutable llamado python para que no
conflicte con un ejecutable de Python 2.x que est instalado simultaneamente.
4.1.1. Nmeros
El intrprete acta como una simple calculadora; pods ingresar una expresin y este escribir los valores. La sintaxis
es sencilla: los operadores+, -, * y / funcionan como en la mayora de los lenguajes (por ejemplo, Pascal o C); los
parntesis (()) pueden ser usados para agrupar. Por ejemplo:
>>> 2 + 2
4
>>> 50 - 5*6
20
>>> (50 - 5*6) / 4
5.0
>>> 8 / 5
1.6
Los nmeros enteros (por ejemplo 2, 4, 20) son de tipo int, aquellos con una parte fraccional (por ejemplo 5.0, 1.6)
son de tipo float. Vamos a ver ms sobre tipos de nmeros luego en este tutorial.
La divisin (/) siempre retorna un punto flotante. Para hacer floor division y obtener un resultado entero (descartando
cualquier resultado fraccional) pods usar el operador //; para calcular el resto pods usar %:
>>> 17 / 3
5.666666666666667
>>>
>>> 17 // 3
5
>>> 17 % 3
2
>>> 5 * 3 + 2
17
# 5 al cuadrado
25
>>> 2 ** 7
# 2 a la potencia de 7
128
El signo igual (=) es usado para asignar un valor a una variable. Luego, ningn resultado es mostrado antes del
prximo prompt:
>>> ancho = 20
>>> largo = 5 * 9
>>> ancho * largo
900
Si una variable no est definida (con un valor asignado), intentar usarla producir un error:
>>> n
En el modo interactivo, la ltima expresin impresa es asignada a la variable _. Esto significa que cuando ests
usando Python como una calculadora de escritorio, es ms fcil seguir calculando, por ejemplo:
>>> impuesto = 12.5 / 100
>>> precio = 100.50
>>> precio * impuesto
12.5625
>>> precio + _
113.0625
>>> round(_, 2)
113.06
Esta variable debera ser tratada como de slo lectura por el usuario. No le asignes explcitamente un valor; crears
una variable local independiente con el mismo nombre enmascarando la variable con el comportamiento mgico.
Adems de int y float, Python soporta otros tipos de nmeros, como ser Decimal y Fraction. Python tambin
tiene soporte integrado para nmeros complejos, y usa el sufijo j o J para indicar la parte imaginaria (por
ejemplo 3+5j).
# comillas simples
'huevos y pan'
>>> 'doesn\'t'
"doesn't"
>>> "doesn't"
"doesn't"
>>> '"Si," le dijo.'
'"Si," le dijo.'
>>> "\"Si,\" le dijo."
'"Si," le dijo.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
En el intprete interactivo, la salida de cadenas est encerrada en comillas y los caracteres especiales son escapados
con barras invertidas. Aunque esto a veces luzca diferente de la entrada (las comillas que encierran pueden cambiar),
las dos cadenas son equivalentes. La cadena se encierra en comillas dobles si la cadena contiene una comilla simple
y ninguna doble, de lo contrario es encerrada en comillas simples. La funcin print() produce una salida ms
legible,omitiendo las comillas que la encierran e imprimiendo caracteres especiales y escapados:
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
>>> print('"Isn\'t," she said.')
"Isn't," she said.
>>> s = 'Primerea lnea.\nSegunda lnea.'
>>> s
Primera lnea.
Segunda lnea.
Si no quers que los caracteres antepuestos por \ sean interpretados como caracteres especiales, pods
usar cadenas crudas agregando una rantes de la primera comilla:
>>> print('C:\algun\nombre')
C:\algun
ombre
>>> print(r'C:\algun\nombre')
C:\algun\nombre
Las cadenas de texto literales pueden contener mltiples lneas. Una forma es usar triple
comillas: """...""" o '''...'''. Los fin de lnea son includos automticamente, pero es posible prevenir esto
agregando una \ al final de la lnea. Por ejemplo:
print("""\
Uso: algo [OPTIONS]
-h
-H nombrehost
""")
-H nombrehost
Las cadenas de texto pueden ser concatenadas (pegadas juntas) con el operador + y repetidas con *:
>>> # 3 veces 'un', seguido de 'ium'
>>> 3 * 'un' + 'ium'
'unununium'
Dos o ms cadenas literales (aquellas encerradas entre comillas) una al lado de la otra son automticamente
concatenadas:
>>> 'Py' 'thon'
'Python'
...
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
...
SyntaxError: invalid syntax
Las cadenas de texto se pueden indexar (subndices), el primer carcter de la cadena tiene el ndice 0. No hay un tipo
de dato para los caracteres; un carcter es simplemente una cadena de longitud uno:
>>> palabra = 'Python'
>>> palabra[0]
# caracter en la posicin 0
'P'
>>> palabra[5]
# caracter en la posicin 5
'n'
Los ndices quizs sean nmeros negativos, para empezar a contar desde la dereche:
>>> palabra[-1]
# ltimo caracter
'n'
>>> palabra[-2]
'o'
>>> palabra[-6]
'P'
Nota que -0 es lo mismo que 0, los ndice negativos comienzan desde -1.
Adems de los ndices, las rebanadas tambin estn soportadas. Mientras que los ndices son usados para obtener
caracteres individuales, las rebanadas te permiten obtener sub-cadenas:
>>> palabra[0:2]
'Py'
>>> palabra[2:5]
'tho'
Nota como el primero es siempre includo, y que el ltimo es siempre excludo. Esto asegura
que s[:i] + s[i:] siempre sea igual a s:
>>> palabra[:2] + palabra[2:]
'Python'
>>> palabra[:4] + palabra[4:]
'Python'
Los ndices de las rebanadas tienen valores por defecto tiles; el valor por defecto para el primer ndice es cero, el
valor por defecto para el segundo ndice es la longitud de la cadena a rebanar.
>>> palabra[:2]
'Py'
>>> palabra[4:]
'on'
>>> palabra[-2:] # caracteres desde la ante-ltima (includa) hasta el final
'on'
Una forma de recordar cmo funcionan las rebanadas es pensar en los ndices como puntos entre caracteres, con el
punto a la izquierda del primer carcter numerado en 0. Luego, el punto a la derecha del ltimo carcter de una
cadena de n caracteres tienen ndice n, por ejemplo:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0
-6
-5
-4
-3
-2
-1
La primer fila de nmeros da la posicin de los ndices 0...6 en la cadena; la segunda fila da los correspondientes
ndices negativos. La rebanada de i a j consiste en todos los caracteres entre los puntos etiquetados i y j,
respectivamente.
Para ndices no negativos, la longitud de la rebanada es la diferencia de los ndices, si ambos entran en los lmites.
Por ejemplo, la longitud de palabra[1:3] es 2.
Intentar usar un ndice que es muy grande resultar en un error:
>>> palabra[42]
Las cadenas de Python no pueden ser modificadas son immutable. Por eso, asignar a una posicin indexada de la
cadena resulta en un error:
>>> palabra[0] = 'J'
...
TypeError: 'str' object does not support item assignment
>>> palabra[2:] = 'py'
...
TypeError: 'str' object does not support item assignment
'Jython'
>>> palabra[:2] + 'py'
'Pypy'
Ver tambin
Tipos integrados
Las cadenas de texto son ejemplos de tipos secuencias, y soportan las operaciones comunes para esos tipos.
Tipos integrados
Las cadenas de texto soportan una gran cantidad de mtodos para transformaciones bsicas y bsqueda.
Tipos integrados
Aqu se da informacin sobre formateo de cadenas de texto con str.format().
Tipos integrados
Aqu se describe con ms detalle las operaciones viejas para formateo usadas cuando una cadena de texto o
una cadena Unicode estn a la izquierda del operador %.
4.1.3. Listas
Python tiene varios tipos de datos compuestos, usados para agrupar otros valores. El ms verstil es la lista, la cual
puede ser escrita como una lista de valores separados por coma (tems) entre corchetes. Las listas pueden contener
tems de diferentes tipos, pero usualmente los tems son del mismo tipo:
>>> cuadrados = [1, 4, 9, 16, 25]
>>> cuadrados
[1, 4, 9, 16, 25]
Como las cadenas de caracteres (y todos los otros tipos sequence integrados), las listas pueden ser indexadas y
rebanadas:
>>> cuadrados[0]
1
>>> cuadrados[-1]
25
>>> cuadrados[-3:]
Todas las operaciones de rebanado devuelven una nueva lista conteniendo los elementos pedidos. Esto significa que
la siguiente rebanada devuelve una copia superficial de la lista:
>>> cuadrados[:]
[1, 4, 9, 16, 25]
A diferencia de las cadenas de texto, que son immutable, las listas son un tipo mutable, es posible cambiar un su
contenido:
>>> cubos = [1, 8, 27, 65, 125]
>>> 4 ** 3
64
>>> cubos[3] = 64
>>> cubos
[1, 8, 27, 64, 125]
Tambin pods agregar nuevos tems al final de la lista, usando el mtodo append() (vamos a ver ms sobre los
mtodos luego):
>>> cubos.append(216)
# agregar el cubo de 6
>>> cubos.append(7 ** 3)
# y el cubo de 7
>>> cubos
[1, 8, 27, 64, 125, 216, 343]
Tambin es posible asignar a una rebanada, y esto incluso puede cambiar la longitud de la lista o vaciarla totalmente:
>>> letras = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letras
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> # reemplazar algunos valores
>>> letras[2:5] = ['C', 'D', 'E']
>>> letras
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> # ahora borrarlas
>>> letras[2:5] = []
>>> letras
['a', 'b', 'f', 'g']
>>> # borrar la lista reemplzando todos los elementos por una lista vaca
>>> letras[:] = []
>>> letras
[]
Es posible anidar listas (crear listas que contengan otras listas), por ejemplo:
>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'
print(b)
...
a, b = b, a+b
...
1
1
2
3
5
8
La primer lnea contiene una asignacin mltiple: las variables a y b toman en forma simultanea los nuevos
valores 0 y 1. En la ltima linea esto se vuelve a usar, demostrando que las expresiones a la derecha son
evaluadas antes de que suceda cualquier asignacin. Las expresiones a la derecha son evaluadas de
izquierda a derecha.
El bucle while se ejecuta mientras la condicin (aqu: b < 10) sea verdadera. En Python, como en C,
cualquier entero distinto de cero es verdadero; cero es falso. La condicin tambin puede ser una cadena de
texto o una lista, de hecho cualquier secuencia; cualquier cosa con longitud distinta de cero es verdadero, las
secuencias vacas son falsas. La prueba usada en el ejemplo es una comparacin simple. Los operadores
estndar de comparacin se escriben igual que en C: < (menor qu), > (mayor qu), == (igual a), <= (menor o
igual qu), >=(mayor o igual qu) y != (distinto a).
El cuerpo del bucle est sangrado: la sangra es la forma que usa Python para agrupar declaraciones. En el
intrprete interactivo debs teclear un tab o espacio(s) para cada lnea sangrada. En la prctica vas a preparar
entradas ms complicadas para Python con un editor de texto; todos los editores de texto decentes tienen la
facilidad de agregar la sangra automticamente. Al ingresar una declaracin compuesta en forma interactiva,
debs finalizar con una lnea en blanco para indicar que est completa (ya que el analizador no puede adivinar
cuando tecleaste la ltima lnea). Not que cada lnea de un bloque bsico debe estar sangrada de la misma
forma.
La funcin print() escribe el valor de el o los argumentos que se le pasan. Difiere de simplemente escribir la
expresin que se quiere mostrar (como hicimos antes en los ejemplos de la calculadora) en la forma en que
maneja mltiples argumentos, cantidades en punto flotante, y cadenas. Las cadenas de texto son impresas sin
comillas, y un espacio en blanco es insertado entre los elementos, as pods formatear cosas de una forma
agradable:
>>> i = 256*256
El valor de i es 65536
El parmetro nombrado end puede usarse para evitar el salto de linea al final de la salida, o terminar la salida
con una cadena diferente:
>>> a, b = 0, 1
>>> while b < 1000:
...
print(b, end=',')
...
a, b = b, a+b
...
1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,
Footnotes
[1]
Debido a que ** tiene mayor precedencia que -, -3**2 ser interpretado como -(3**2) y eso da como resultado 9. Para evitar esto y obtener 9, pods usar (-3)**2.
[2]
A diferencia de otros lenguajes, caracteres especiales como \n tiene el mismo significado con simple ('...') y
doble ("...") comillas. La nica diferencia entre las dos es que dentro de las comillas simples no tens la
necesitada de escapar " (pero tens que escapar \') y viceversa.
5.1. La sentencia if
Tal vez el tipo ms conocido de sentencia sea el if. Por ejemplo:
>>> x = int(input("Ingresa un entero, por favor: "))
Ingresa un entero, por favor: 42
>>> if x < 0:
...
x = 0
...
... elif x == 0:
...
print('Cero')
... elif x == 1:
...
print('Simple')
... else:
...
print('Ms')
...
'Mas'
Puede haber cero o ms bloques elif, y el bloque else es opcional. La palabra reservada elif es una abreviacin
de else if, y es til para evitar un sangrado excesivo. Una secuencia if ... elif ... elif ... sustituye las
sentencias switch o case encontradas en otros lenguajes.
print(p, len(p))
...
gato 4
ventana 7
defenestrado 12
Si necesits modificar la secuencia sobre la que ests iterando mientras ests adentro del ciclo (por ejemplo para
borrar algunos tems), se recomienda que hagas primero una copia. Iterar sobre una secuencia no hace
implcitamente una copia. La notacin de rebanada es especialmente conveniente para esto:
>>> for p in palabras[:]:
...
...
if len(p) > 6:
palabras.insert(0, p)
...
>>> palabras
['defenestrado', 'ventana', 'gato', 'ventana', 'defenestrado']
print(i)
...
0
1
2
3
4
El valor final dado nunca es parte de la secuencia; range(10) genera 10 valores, los ndices correspondientes para los
tems de una secuencia de longitud 10. Es posible hacer que el rango empiece con otro nmero, o especificar un
incremento diferente (incluso negativo; algunas veces se lo llama paso):
range(5, 10)
5 through 9
range(0, 10, 3)
0, 3, 6, 9
Para iterar sobre los ndices de una secuencia, pods combinar range() y len() as:
>>> a = ['Mary', 'tenia', 'un', 'corderito']
>>> for i in range(len(a)):
...
print(i, a[i])
...
0 Mary
1 tenia
2 un
3 corderito
En la mayora de los casos, sin embargo, conviene usar la funcin enumerate(), mir Tcnicas de iteracin.
Algo extrao sucede si mostrs un range:
>>> print(range(10))
range(0, 10)
De muchas maneras el objeto devuelto por range() se comporta como si fuera una lista, pero no lo es. Es un objeto
que devuelve los tems sucesivos de la secuencia deseada cuando iters sobre l, pero realmente no construye la
lista, ahorrando entonces espacio.
Decimos que tal objeto es iterable; esto es, que se lo puede usar en funciones y construcciones que esperan algo de
lo cual obtener tems sucesivos hasta que se termine. Hemos visto que la declaracin for es un iterador en ese
sentido. La funcin list() es otra; crea listas a partir de iterables:
>>> list(range(5))
[0, 1, 2, 3, 4]
Ms tarde veremos ms funciones que devuelven iterables y que toman iterables como entrada.
...
if n % x == 0:
...
...
break
...
else:
...
...
...
2 es un numero primo
3 es un numero primo
4 es igual a 2 * 2
5 es un numero primo
6 es igual a 2 * 3
7 es un numero primo
8 es igual a 2 * 4
9 es igual a 3 * 3
(S, este es el cdigo correcto. Fijate bien: el else pertenece al ciclo for, no al if.)
Cuando se usa con un ciclo, el else tiene ms en comn con el else de una declaracin try que con el de un if:
el else de un try se ejecuta cuando no se genera ninguna excepcin, y el else de un ciclo se ejecuta cuando no hay
ningn break. Para ms sobre la declaracin try y excepciones, mir Manejando excepciones.
La declaracin continue, tambin tomada de C, continua con la siguiente iteracin del ciclo:
>>> for num in range(2, 10):
...
if num % 2 == 0:
...
...
continue
...
pass
...
pass
...
Otro lugar donde se puede usar pass es como una marca de lugar para una funcin o un cuerpo condicional cuando
ests trabajando en cdigo nuevo, lo cual te permite pensar a un nivel de abstraccin mayor. El pass se ignora
silenciosamente:
>>> def initlog(*args):
...
pass
...
...
a, b = 0, 1
...
while a < n:
...
...
a, b = b, a+b
...
print()
...
>>> # Ahora llamamos a la funcion que acabamos de definir:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
La palabra reservada def se usa para definir funciones. Debe seguirle el nombre de la funcin y la lista de parmetros
formales entre parntesis. Las sentencias que forman el cuerpo de la funcin empiezan en la lnea siguiente, y deben
estar con sangra.
La primer sentencia del cuerpo de la funcin puede ser opcionalmente una cadena de texto literal; esta es la cadena
de texto de documentacin de la funcin, o docstring. (Pods encontrar ms acerca de docstrings en la
seccin Cadenas de texto de documentacin.)
Hay herramientas que usan las docstrings para producir automticamente documentacin en lnea o imprimible, o
para permitirle al usuario que navegue el cdigo en forma interactiva; es una buena prctica incluir docstrings en el
cdigo que uno escribe, por lo que se debe hacer un hbito de esto.
La ejecucin de una funcin introduce una nueva tabla de smbolos usada para las variables locales de la funcin.
Ms precisamente, todas las asignaciones de variables en la funcin almacenan el valor en la tabla de smbolos local;
as mismo la referencia a variables primero mira la tabla de smbolos local, luego en la tabla de smbolos local de las
funciones externas, luego la tabla de smbolos global, y finalmente la tabla de nombres predefinidos. As, no se les
puede asignar directamente un valor a las variables globales dentro de una funcin (a menos se las nombre en la
sentencia global), aunque si pueden ser referenciadas.
Los parmetros reales (argumentos) de una funcin se introducen en la tabla de smbolos local de la funcin llamada
cuando esta es ejecutada; as, los argumentos son pasados por valor (dnde el valor es siempre una referencia a un
objeto, no el valor del objeto). [1] Cuando una funcin llama a otra funcin, una nueva tabla de smbolos local es creada
para esa llamada.
La definicin de una funcin introduce el nombre de la funcin en la tabla de smbolos actual. El valor del nombre de la
funcin tiene un tipo que es reconocido por el interprete como una funcin definida por el usuario. Este valor puede
ser asignado a otro nombre que luego puede ser usado como una funcin. Esto sirve como un mecanismo general
para renombrar:
>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89
Viniendo de otros lenguajes, pods objetar que fib no es una funcin, sino un procedimiento, porque no devuelve un
valor. De hecho, tcnicamente hablando, los procedimientos s retornan un valor, aunque uno aburrido. Este valor se
llama None (es un nombre predefinido). El intrprete por lo general no escribe el valor None si va a ser el nico valor
escrito. Si realmente se quiere, se puede verlo usando la funcinprint():
>>> fib(0)
>>> print(fib(0))
None
Es simple escribir una funcin que retorne una lista con los nmeros de la serie de Fibonacci en lugar de imprimirlos:
>>> def fib2(n): # devuelve la serie de Fibonacci hasta n
...
...
result = []
...
a, b = 0, 1
...
while a < n:
...
result.append(a)
...
a, b = b, a+b
# ver abajo
return result
...
...
# llamarla
>>> f100
# escribir el resultado
La sentencia return devuelve un valor en una funcin. return sin una expresin como argumento
retorna None. Si se alcanza el final de una funcin, tambin se retorna None.
La sentencia result.append(a) llama a un mtodo del objeto lista result. Un mtodo es una funcin que
pertenece a un objeto y se nombra obj.methodname, dnde obj es algn objeto (puede ser una expresin),
y methodname es el nombre del mtodo que est definido por el tipo del objeto. Distintos tipos definen distintos
mtodos. Mtodos de diferentes tipos pueden tener el mismo nombre sin causar ambigedad. (Es posible
definir tipos de objetos propios, y mtodos, usando clases, mir Clases). El mtodo append() mostrado en el
ejemplo est definido para objetos lista; aade un nuevo elemento al final de la lista. En este ejemplo es
equivalente aresult = result + [a], pero ms eficiente.
reintentos = reintentos - 1
if reintentos < 0:
raise OSError('usuario duro')
print(queja)
Este ejemplo tambin introduce la palabra reservada in, la cual prueba si una secuencia contiene o no un
determinado valor.
Los valores por omisin son evaluados en el momento de la definicin de la funcin, en el mbito de la definicin,
entonces:
i = 5
def f(arg=i):
print(arg)
i = 6
f()
...imprimir 5.
Advertencia importante: El valor por omisin es evaluado solo una vez. Existe una diferencia cuando el valor por
omisin es un objeto mutable como una lista, diccionario, o instancia de la mayora de las clases. Por ejemplo, la
siguiente funcin acumula los argumentos que se le pasan en subsiguientes llamadas:
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
Imprimir:
[1]
[1, 2]
[1, 2, 3]
Si no se quiere que el valor por omisin sea compartido entre subsiguientes llamadas, se pueden escribir la funcin
as:
...acepta un argumento obligatorio (tension) y tres argumentos opcionales (estado, accion, y tipo). Esta funcin
puede llamarse de cualquiera de las siguientes maneras:
loro(1000)
# 1 argumento posicional
loro(tension=1000)
# 1 argumento nombrado
loro(tension=1000000, accion='VOOOOOM')
# 2 argumentos nombrados
loro(accion='VOOOOOM', tension=1000000)
# 2 argumentos nombrados
# 3 args posicionales
# uno y uno
loro(actor='Juan Garau')
En una llamada a una funcin, los argumentos nombrados deben seguir a los argumentos posicionales. Cada uno de
los argumentos nombrados pasados deben coincidir con un argumento aceptado por la funcin (por ejemplo, actor no
es un argumento vlido para la funcin loro), y el orden de los mismos no es importante. Esto tambin se aplica a los
argumentos obligatorios (por ejemplo, loro(tension=1000) tambin es vlido). Ningn argumento puede recibir ms
de un valor al mismo tiempo. Aqu hay un ejemplo que falla debido a esta restriccin:
>>> def funcion(a):
...
pass
...
>>> funcion(0, a=0)
Traceback (most recent call last):
...
Cuando un parmetro formal de la forma **nombre est presente al final, recibe un diccionario (ver Tipos integrados)
conteniendo todos los argumentos nombrados excepto aquellos correspondientes a un parmetro formal. Esto puede
ser combinado con un parmetro formal de la forma*nombre (descripto en la siguiente seccin) que recibe una tupla
conteniendo los argumentos posicionales adems de la lista de parmetros formales. (*nombre debe ocurrir antes
de **nombre). Por ejemplo, si definimos una funcin as:
def ventadequeso(tipo, *argumentos, **palabrasclaves):
print("-- Tiene", tipo, "?")
print("-- Lo siento, nos quedamos sin", tipo)
for arg in argumentos:
print(arg)
print("-" * 40)
claves = sorted(palabrasclaves.keys())
for c in claves:
print(c, ":", palabrasclaves[c])
Se debe notar que la lista de nombres de argumentos nombrados se crea al ordenar el resultado del
mtodo keys() del diccionario antes de imprimir su contenido; si esto no se hace, el orden en que los argumentos son
impresos no est definido.
Normalmente estos argumentos de cantidad variables son los ltimos en la lista de parmetros formales, porque
toman todo el remanente de argumentos que se pasan a la funcin. Cualquier parmetro que suceda luego
del *args ser slo nombrado, o sea que slo se pueden usar como nombrados y no posicionales.:
>>> def concatenar(*args, sep="/"):
...
return sep.join(args)
...
>>> concatenar("tierra", "marte", "venus")
'tierra/marte/venus'
>>> concatenar("tierra", "marte", "venus", sep=".")
'tierra.marte.venus'
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args))
[3, 4, 5]
Del mismo modo, los diccionarios pueden entregar argumentos nombrados con el operador **::
>>> def loro(tension, estado='rostizado', accion='explotar'):
...
...
...
...
>>> d = {"tension": "cinco mil", "estado": "demacrado",
...
"accion": "VOLAR"}
>>> loro(**d)
-- Este loro no va a VOLAR si le aplics cinco mil voltios. Est demacrado !
solo azcar sintctica para definiciones normales de funciones. Al igual que las funciones anidadas, las funciones
lambda pueden hacer referencia a variables desde el mbito que la contiene:
>>> def hacer_incrementador(n):
...
return lambda x: x + n
...
>>> f = hacer_incrementador(42)
>>> f(0)
42
>>> f(1)
43
...
...
...
"""
...
pass
...
>>> print(mi_funcion.__doc__)
No hace mas que documentar la funcion.
print("Anotaciones:", f.__annotations__)
...
...
...
>>> f('carne')
Anotaciones: {'jamon': <class 'str'>, 'huevos': <class 'str'>, 'return': <class 'str'>}
Argumentos: carne huevos
'carne y huevos'
>>>
Usar lneas en blanco para separar funciones y clases, y bloques grandes de cdigo dentro de funciones.
Usar docstrings.
Usar espacios alrededor de operadores y luego de las comas, pero no directamente dentro de
parntesis: a = f(1, 2) + g(3, 4).
Nombrar las clases y funciones consistentemente; la convencin es usar NotacionCamello para clases
y minusculas_con_guiones_bajospara funciones y mtodos. Siempre us self como el nombre para el primer
argumento en los mtodos (mir Un primer vistazo a las clasespara ms informacin sobre clases y mtodos).
De la misma manera, no uses caracteres no-ASCII en los identificadores si hay incluso una pequesima
chance de que gente que hable otro idioma tenga que leer o mantener el cdigo.
Footnotes
[1]
En realidad, llamadas por referencia de objeto sera una mejor descripcin, ya que si se pasa un objeto mutable,
quien realiza la llamada ver cualquier cambio que se realice sobre el mismo (por ejemplo tems insertados en una
lista).
6. Estructuras de datos
Este captulo describe algunas cosas que ya aprendiste en ms detalle, y agrega algunas cosas nuevas tambin.
Extiende la lista agregndole todos los tems de la lista dada. Equivale a a[len(a):] = L.
list.insert(i, x)
Inserta un tem en una posicin dada. El primer argumento es el ndice del tem delante del cual se insertar,
por lo tanto a.insert(0, x) inserta al principio de la lista, y a.insert(len(a), x) equivale a a.append(x).
list.remove(x)
Quita el primer tem de la lista cuyo valor sea x. Es un error si no existe tal tem.
list.pop([i])
Quita el tem en la posicin dada de la lista, y lo devuelve. Si no se especifica un ndice, a.pop() quita y
devuelve el ltimo tem de la lista. (Los corchetes que encierran a i en la firma del mtodo denotan que el
parmetro es opcional, no que deberas escribir corchetes en esa posicin. Vers esta notacin con frecuencia
en la Referencia de la Biblioteca de Python.)
list.clear()
Devuelve el ndice en la lista del primer tem cuyo valor sea x. Es un error si no existe tal tem.
list.count(x)
Ordena los tems de la lista in situ (los argumentos pueden ser usados para personalizar el orden de la lista,
ve sorted() para su explicacin).
list.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
>>> a.sort()
>>> a
[-1, 1, 66.25, 333, 333, 1234.5]
>>> a.pop()
1234.5
>>> a
[-1, 1, 66.25, 333, 333]
Quizs hayas notado que mtodos como insert, remove o sort, que solo modifican a la lista, no tienen impreso un
valor de retorno devuelven None. [1] Esto es un principio de diseo para todas las estructuras de datos mutables en
Python.
# llega Terry
>>> queue.append("Graham")
# llega Graham
>>> queue.popleft()
'Eric'
>>> queue.popleft()
'John'
>>> queue
cuadrados.append(x**2)
...
>>> cuadrados
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Nota que esto crea (o sobreescribe) una variable llamada x que sigue existiendo luego de que el bucle haya
terminado. Podemos calcular la lista de cuadrados sin ningun efecto secundario haciendo:
cuadrados = list(map(lambda x: x**2, range(10)))
o, un equivalente:
cuadrados = [x ** 2 for x in range(10)]
y es equivalente a:
>>> combs = []
for y in [3,1,4]:
...
if x != y:
combs.append((x, y))
...
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
banana', '
']
[1, 2, 3, 4],
...
[5, 6, 7, 8],
...
... ]
Como vimos en la seccin anterior, la lista de comprensin anidada se evalua en el contexto del for que lo sigue, por
lo que este ejemplo equivale a:
>>> transpuesta = []
>>> for i in range(4):
...
...
>>> transpuesta
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
...
fila_transpuesta = []
...
...
fila_transpuesta.append(fila[i])
...
transpuesta.append(fila_transpuesta)
...
>>> transpuesta
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
En el mundo real, deberas preferir funciones predefinidas a declaraciones con flujo complejo. La funcin zip() hara
un buen trabajo para este caso de uso:
>>> list(zip(*matriz))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
Ver Desempaquetando una lista de argumentos para detalles en el asterisco de esta lnea.
Hacer referencia al nombre a de aqu en ms es un error (al menos hasta que se le asigne otro valor). Veremos otros
usos para del ms adelante.
Como puedes ver, en la salida las tuplas siempre se encierran entre parntesis, para que las tuplas anidadas puedan
interpretarse correctamente; pueden ingresarse con o sin parntesis, aunque a menudo los parntesis son necesarios
de todas formas (si la tupla es parte de una expresin ms grande). No es posible asignar a los tems individuales de
una tupla, pero sin embargo s se puede crear tuplas que contengan objetos mutables, como las listas.
A pesar de que las tuplas puedan parecerse a las listas, frecuentemente se utilizan en distintas situaciones y para
distintos propsitos. Las tuplas son inmutables y normalmente contienen una secuencia heterognea de elementos
que son accedidos al desempaquetar (ver ms adelante en esta seccin) o indizar (o incluso acceder por atributo en
el caso de las namedtuples). Las listas son mutables, y sus elementos son normalmente homogneos y se acceden
iterando a la lista.
Un problema particular es la construccin de tuplas que contengan 0 o 1 tem: la sintaxis presenta algunas
peculiaridades para estos casos. Las tuplas vacas se construyen mediante un par de parntesis vaco; una tupla con
un tem se construye poniendo una coma a continuacin del valor (no alcanza con encerrar un nico valor entre
parntesis). Feo, pero efectivo. Por ejemplo:
>>> vacia = ()
>>> singleton = 'hola',
>>> len(vacia)
0
>>> len(singleton)
1
>>> singleton
('hola',)
Esto se llama, apropiadamente, desempaquetado de secuencias, y funciona para cualquier secuencia en el lado
derecho del igual. El desempaquetado de secuencias requiere que la cantidad de variables a la izquierda del signo
igual sea el tamao de la secuencia. Not que la asignacin mltiple es en realidad slo una combinacin de
empaquetado de tuplas y desempaquetado de secuencias.
6.4. Conjuntos
Python tambin incluye un tipo de dato para conjuntos. Un conjunto es una coleccin no ordenada y sin elementos
repetidos. Los usos bsicos de stos incluyen verificacin de pertenencia y eliminacin de entradas duplicadas. Los
conjuntos tambin soportan operaciones matemticas como la unin, interseccin, diferencia, y diferencia simtrica.
Las llaves o la funcin set() pueden usarse para crear conjuntos. Not que para crear un conjunto vaco tens que
usar set(), no {}; esto ltimo crea un diccionario vaco, una estructura de datos que discutiremos en la seccin
siguiente.
Una pequea demostracin:
>>> canasta = {'manzana', 'naranja', 'manzana', 'pera', 'naranja', 'banana'}
>>> print fruta
True
>>> 'yerba' in canasta
False
>>> # veamos las operaciones para las letras nicas de dos palabras
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a
# letras nicas en a
# letras en a pero no en b
# letras en a o en b
# letras en a y en b
{'a', 'c'}
>>> a ^ b
De forma similar a las comprensiones de listas, est tambin soportada la comprensin de conjuntos:
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}
6.5. Diccionarios
Otro tipo de dato til includo en Python es el diccionario (ver Tipos integrados). Los diccionarios se encuentran a
veces en otros lenguajes como memorias asociativas o arreglos asociativos. A diferencia de las secuencias, que se
indexan mediante un rango numrico, los diccionarios se indexan con claves, que pueden ser cualquier tipo inmutable;
las cadenas y nmeros siempre pueden ser claves. Las tuplas pueden usarse como claves si solamente contienen
cadenas, nmeros o tuplas; si una tupla contiene cualquier objeto mutable directa o indirectamente, no puede usarse
como clave. No pods usar listas como claves, ya que las listas pueden modificarse usando asignacin por ndice,
asignacin por seccin, o mtodos como append() y extend().
Lo mejor es pensar en un diccionario como un conjunto no ordenado de pares clave: valor, con el requerimiento de
que las claves sean nicas (dentro de un diccionario en particular). Un par de llaves crean un diccionario vaco: {}.
Colocar una lista de pares clave:valor separados por comas entre las llaves aade pares clave:valor iniciales al
diccionario; esta tambin es la forma en que los diccionarios se presentan en la salida.
Las operaciones principales sobre un diccionario son guardar un valor con una clave y extraer ese valor dada la clave.
Tambin es posible borrar un par clave:valor con del. Si uss una clave que ya est en uso para guardar un valor, el
valor que estaba asociado con esa clave se pierde. Es un error extraer un valor usando una clave no existente.
Hacer list(d.keys()) en un diccionario devuelve una lista de todas las claves usadas en el diccionario, en un orden
arbitrario (si las quers ordenadas, us en cambio sorted(d.keys()). [2] Para controlar si una clave est en el
diccionario, us el in.
Un pequeo ejemplo de uso de un diccionario:
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'jack': 4098, 'guido': 4127}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'jack': 4098, 'irv': 4127, 'guido': 4127}
>>> list(tel.keys())
['irv', 'guido', 'jack']
>>> sorted(tel.keys())
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
>>> 'jack' not in tel
False
Adems, las comprensiones de diccionarios se pueden usar para crear diccionarios desde expresiones arbitrarias de
clave y valor:
>>> {x: x ** 2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
Cuando las claves son cadenas simples, a veces resulta ms fcil especificar los pares usando argumentos por
palabra clave:
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}
print(k, v)
...
gallahad el puro
robin el valiente
Cuando se itera sobre una secuencia, se puede obtener el ndice de posicin junto a su valor correspondiente usando
la funcin enumerate().
>>> for i, v in enumerate(['ta', 'te', 'ti']):
...
print(i, v)
...
0 ta
1 te
2 ti
Para iterar sobre dos o ms secuencias al mismo tiempo, los valores pueden emparejarse con la funcin zip().
>>> preguntas = ['nombre', 'objetivo', 'color favorito']
>>> respuestas = ['lancelot', 'el santo grial', 'azul']
>>> for p, r in zip(preguntas, respuestas):
...
print('Cual es tu {0}?
{1}.'.format(p, r))
...
Cual es tu nombre?
Cual es tu objetivo?
lancelot.
el santo grial.
azul.
Para iterar sobre una secuencia en orden inverso, se especifica primero la secuencia al derecho y luego se llama a la
funcin reversed().
>>> for i in reversed(range(1, 10, 2)):
...
...
9
print(i)
7
5
3
1
Para iterar sobre una secuencia ordenada, se utiliza la funcin sorted() la cual devuelve una nueva lista ordenada
dejando a la original intacta.
>>> canasta = ['manzana', 'naranja', 'manzana', 'pera', 'naranja', 'banana']
>>> for f in sorted(set(canasta)):
...
print(f)
...
banana
manzana
naranja
pera
A veces uno intenta cambiar una lista mientras la est iterando; sin embargo, a menudo es ms simple y seguro crear
una nueva lista:
>>> datos = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> datos_filtrados = []
>>> for valor in datos:
...
...
if not math.isnan(valor):
datos_filtrados.append(valor)
...
>>> datos_filtrados
[56.2, 51.7, 55.3, 52.5, 47.8]
Los operadores booleanos and y or son los llamados operadores cortocircuito: sus argumentos se evalan de
izquierda a derecha, y la evaluacin se detiene en el momento en que se determina su resultado. Por ejemplo,
si A y C son verdaderas pero B es falsa, en A and B and Cno se evala la expresin C. Cuando se usa como un valor
general y no como un booleano, el valor devuelto de un operador cortocircuito es el ltimo argumento evaluado.
Es posible asignar el resultado de una comparacin u otra expresin booleana a una variable. Por ejemplo,
>>> cadena1, cadena2, cadena3 = '', 'Trondheim', 'Paso Hammer'
>>> non_nulo = cadena1 or cadena2 or cadena3
>>> non_nulo
'Trondheim'
Not que en Python, a diferencia de C, la asignacin no puede ocurrir dentro de expresiones. Los programadores de
C pueden renegar por esto, pero es algo que evita un tipo de problema comn encontrado en programas en C:
escribir = en una expresin cuando lo que se quiere escribir es==.
< (1, 2, 4)
[1, 2, 3]
< [1, 2, 4]
< (1, 2, 4)
(1, 2)
(1, 2, 3)
(1, 2, ('aa', 'ab'))
Observ que comparar objetos de diferentes tipos con < o > es legal siempre y cuando los objetas tenga los mtodos
de comparacin apropiados. Por ejemplo, los tipos de nmeros mezclados son comparados de acuerdo a su valor
numrico, o sea 0 es igual a 0.0, etc. Si no es el caso, en lugar de proveer un ordenamiento arbitrario, el intrprete
generar una excepcin TypeError.
Footnotes
[1]
Otros lenguajes pueden devolver el objeto mutado, lo cual permite encadenado de mtodos, como d>insert("a")->remove("b")->sort();.
[2]
Llamar a d.keys() devolver un objeto vista de diccionario. Soporta operaciones como prueba de pertenencia e
iteracin, pero sus contenidos dependen del diccionario original son slo una vista.
7. Mdulos
Si sals del intrprete de Python y entrs de nuevo, las definiciones que hiciste (funciones y variables) se pierden. Por
lo tanto, si quers escribir un programa ms o menos largo, es mejor que uses un editor de texto para preparar la
entrada para el interprete y ejecutarlo con ese archivo como entrada. Esto es conocido como crear un guin, o script.
Si tu programa se vuelve ms largo, quizs quieras separarlo en distintos archivos para un mantenimiento ms fcil.
Quizs tambin quieras usar una funcin til que escribiste desde distintos programas sin copiar su definicin a cada
programa.
Para soportar esto, Python tiene una manera de poner definiciones en un archivo y usarlos en un script o en una
instancia interactiva del intrprete. Tal archivo es llamado mdulo; las definiciones de un mdulo pueden
ser importadas a otros mdulos o al mdulo principal (la coleccin de variables a las que tens acceso en un script
ejecutado en el nivel superior y en el modo calculadora).
Un mdulo es una archivo conteniendo definiciones y declaraciones de Python. El nombre del archivo es el nombre
del mdulo con el sufijo .pyagregado. Dentro de un mdulo, el nombre del mismo (como una cadena) est disponible
en el valor de la variable global __name__. Por ejemplo, us tu editor de textos favorito para crear un archivo
llamado fibo.py en el directorio actual, con el siguiente contenido:
# mdulo de nmeros Fibonacci
def fib(n):
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print()
Ahora entr al intrprete de Python e import este mdulo con la siguiente orden:
>>> import fibo
Esto no mete los nombres de las funciones definidas en fibo directamente en el espacio de nombres actual; slo
mete ah el nombre del mdulo,fibo. Usando el nombre del mdulo pods acceder a las funciones:
>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
Esto no introduce en el espacio de nombres local el nombre del mdulo desde el cual se est importando (entonces,
en el ejemplo, fibo no se define).
Hay incluso una variante para importar todos los nombres que un mdulo define:
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Esto importa todos los nombres excepto aquellos que comienzan con un subrayado (_). La mayora de las veces los
programadores de Python no usan esto ya que introduce un conjunto de nombres en el intrprete, posiblemente
escondiendo cosas que ya estaban definidas.
Not que en general la prctica de importar * de un mdulo o paquete est muy mal vista, ya que frecuentemente
genera un cdigo poco legible. Sin embargo, est bien usarlo para ahorrar tecleo en sesiones interactivas.
Nota
Por razones de eficiencia, cada mdulo se importa una vez por sesin del intrprete. Por lo tanto, si modifics los
mdulos, tens que reiniciar el intrprete o, si es slo un mdulo que quers probar interactivamente,
us imp.reload(), por ejemploimport imp; imp.reload(nombremodulo).
...el cdigo en el mdulo ser ejecutado, tal como si lo hubieses importado, pero con __name__ con el valor
de "__main__". Eso significa que agregando este cdigo al final de tu mdulo:
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
...pods hacer que el archivo sea utilizable tanto como script, como mdulo importable, porque el cdigo que analiza
la linea de rdenes slo se ejecuta si el mdulo es ejecutado como archivo principal:
$ python fibo.py 50
1 1 2 3 5 8 13 21 34
Esto es frecuentemente usado para proveer al mdulo una interfaz de usuario conveniente, o para propsitos de
prueba (ejecutar el mdulo como un script ejecuta el juego de pruebas).
Nota
En sistemas de archivos que soportan enlaces simblicos, el directorio conteniendo el script de entrada es calculado
despus de que el enlace simblico sea seguido. En otras palabras, el directorio conteniendo el enlace
simblico no es agregado al mdulo de busca del path.
Luego de la inicializacin, los programas Python pueden modificar sys.path. El directorio que contiene el script que
se est ejecutando se ubica al principio de la bsqueda, adelante de la biblioteca estndar. Esto significa que se
cargarn scripts en ese directorio en lugar de mdulos de la biblioteca estndar con el mismo nombre. Esto es un
error a menos que se est reemplazando intencionalmente. Mir la seccin Mdulos estndarpara ms informacin.
Pods usar la -O o -OO en el comando de Python para reducir el tamao de los mdulos compilados. La O quita assert statements, la --Oquita ambos, assert statements y cadenas de caracteres __doc__. Debido a
que algunos programas se basan en que estos estn disponibles, deberas usar esta opcin nicamente si
sabs lo que ests haciendo. Los mdulos optimizados tienen una etiqueta opt- y son normalmente ms
pequeos. Releases futuras quizs cambien los efectos de la optimizacin.
Un programa no corre ms rpido cuando se lee de un archivo .pyc que cuando se lee del .py; lo nico que es
ms rpido en los archivos.pyc es la velocidad con que se cargan.
Hay ms detalles de este proceso, incluyendo un diagrama de flujo de la toma de decisiones, en la PEP 3147.
El mdulo compilleall puede crear archivos .pyc para todos los mdulos en un directorio.
Estas dos variables estn solamente definidas si el intrprete est en modo interactivo.
La variable sys.path es una lista de cadenas que determinan el camino de bsqueda del intrprete para los mdulos.
Se inicializa por omisin a un camino tomado de la variable de entorno PYTHONPATH, o a un valor predefinido en el
intrprete si PYTHONPATH no est configurada. Lo pods modificar usando las operaciones estndar de listas:
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
Sin argumentos, dir() lista los nombres que tens actualmente definidos:
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
Not que lista todos los tipos de nombres: variables, mdulos, funciones, etc.
dir() no lista los nombres de las funciones y variables integradas. Si quers una lista de esos, estn definidos en el
mdulo estndar builtins:
>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
7.4. Paquetes
Los paquetes son una manera de estructurar los espacios de nombres de Python usando nombres de mdulos con
puntos. Por ejemplo, el nombre de mdulo A.B designa un submdulo llamado B en un paquete llamado A. Tal como
el uso de mdulos evita que los autores de diferentes mdulos tengan que preocuparse de los respectivos nombres
de variables globales, el uso de nombres de mdulos con puntos evita que los autores de paquetes de muchos
mdulos, como NumPy o la Biblioteca de Imgenes de Python (Python Imaging Library, o PIL), tengan que
preocuparse de los respectivos nombres de mdulos.
Suponete que quers designar una coleccin de mdulos (un paquete) para el manejo uniforme de archivos y datos
de sonidos. Hay diferentes formatos de archivos de sonido (normalmente reconocidos por su extensin, por
ejemplo: .wav, .aiff, .au), por lo que tens que crear y mantener una coleccin siempre creciente de mdulos para la
conversin entre los distintos formatos de archivos. Hay muchas operaciones diferentes que quizs quieras ejecutar
en los datos de sonido (como mezclarlos, aadir eco, aplicar una funcin ecualizadora, crear un efecto estreo
artificial), por lo que ademas estars escribiendo una lista sin fin de mdulos para realizar estas operaciones. Aqu hay
una posible estructura para tu paquete (expresados en trminos de un sistema jerrquico de archivos):
sound/
Paquete superior
__init__.py
formats/
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/
filters/
Al importar el paquete, Python busca a travs de los directorios en sys.path, buscando el subdirectorio del paquete.
Los archivos __init__.py se necesitan para hacer que Python trate los directorios como que contienen paquetes; esto
se hace para prevenir directorios con un nombre comn, como string, de esconder sin intencin a mdulos vlidos
que se suceden luego en el camino de bsqueda de mdulos. En el caso ms simple, __init__.py puede ser
solamente un archivo vaco, pero tambin puede ejecutar cdigo de inicializacin para el paquete o configurar la
variable __all__, descrita luego.
Los usuarios del paquete pueden importar mdulos individuales del mismo, por ejemplo:
import sound.effects.echo
Esto carga el submdulo sound.effects.echo. Debe hacerse referencia al mismo con el nombre completo.
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
Esto tambin carga el submdulo echo, lo deja disponible sin su prefijo de paquete, por lo que puede usarse as:
echo.echofilter(input, output, delay=0.7, atten=4)
De nuevo, esto carga el submdulo echo, pero deja directamente disponible a la funcin echofilter():
Not que al usar from package import item el tem puede ser tanto un submdulo (o subpaquete) del paquete, o
algn otro nombre definido en el paquete, como una funcin, clase, o variable. La declaracin import primero verifica
si el tem est definido en el paquete; si no, asume que es un mdulo y trata de cargarlo. Si no lo puede encontrar, se
genera una excepcin ImportError.
Por otro lado, cuando se usa la sintaxis como import item.subitem.subsubitem, cada tem excepto el ltimo debe ser
un paquete; el mismo puede ser un mdulo o un paquete pero no puede ser una clase, funcin o variable definida en
el tem previo.
Esto significara que from sound.effects import * importara esos tres submdulos del paquete sound.
Si no se define __all__, la declaracin from sound.effects import * no importa todos los submdulos del
paquete sound.effects al espacio de nombres actual; slo se asegura que se haya importado el
paquete sound.effects (posiblemente ejecutando algn cdigo de inicializacin que haya en __init__.py) y luego
importa aquellos nombres que estn definidos en el paquete. Esto incluye cualquier nombre definido (y submdulos
explcitamente cargados) por __init__.py. Tambin incluye cualquier submdulo del paquete que pudiera haber sido
explcitamente cargado por declaraciones import previas. Consider este cdigo:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
En este ejemplo, los mdulos echo y surround se importan en el espacio de nombre actual porque estn definidos en
el paquete sound.effectscuando se ejecuta la declaracin from...import. (Esto tambin funciona cuando se
define __all__).
A pesar de que ciertos mdulos estn diseados para exportar solo nombres que siguen ciertos patrones cuando
uss import *, tambin se considera una mala prctica en cdigo de produccin.
Record que no est mal usar from paquete import submodulo_especifico! De hecho, esta notacin se recomienda a
menos que el mdulo que ests importando necesite usar submdulos con el mismo nombre desde otros paquetes.
Not que los imports relativos se basan en el nombre del mdulo actual. Ya que el nombre del mdulo principal es
siempre "__main__", los mdulos pensados para usarse como mdulo principal de una aplicacin Python siempre
deberan usar import absolutos.
De hecho las definiciones de funcin son tambin declaraciones que se ejecutan; la ejecucin de una definicin
de funcin a nivel de mdulo mete el nombre de la funcin en el espacio de nombres global.
8. Entrada y salida
Hay diferentes mtodos de presentar la salida de un programa; los datos pueden ser impresos de una forma legible
por humanos, o escritos a un archivo para uso futuro. Este captulo discutir algunas de las posibilidades.
...
...
print(repr(x * x * x).rjust(4))
...
1
27
16
64
25
125
36
216
49
343
64
512
81
729
10 100 1000
...
...
1
27
16
64
25
125
36
216
49
343
64
512
81
729
10 100 1000
(Notar que en el primer ejemplo, un espacio entre cada columna fue agregado por la manera en que print() trabaja:
siempre agrega espacios entre sus argumentos)
Este ejemplo muestra el mtodo str.rjust() de los objetos cadena, el cual ordena una cadena a la derecha en un
campo del ancho dado llenndolo con espacios a la izquierda. Hay mtodos
similares str.ljust() y str.center(). Estos mtodos no escriben nada, slo devuelven una nueva cadena. Si la
cadena de entrada es demasiado larga, no la truncan, sino la devuelven intacta; esto te romper la alineacin de tus
columnas pero es normalmente mejor que la alternativa, que te estara mintiendo sobre el valor. (Si realmente quers
que se recorte, siempre pods agregarle una operacin de rebanado, como en x.ljust(n)[:n].)
Hay otro mtodo, str.zfill(), el cual rellena una cadena numrica a la izquierda con ceros. Entiende signos
positivos y negativos:
>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'
Las llaves y caracteres dentro de las mismas (llamados campos de formato) son reemplazadas con los objetos
pasados en el mtodostr.format(). Un nmero en las llaves se refiere a la posicin del objeto pasado en el
mtodo.
>>> print('{0} y {1}'.format('carne', 'huevos'))
carne y huevos
>>> print('{1} y {0}'.format('carne', 'huevos'))
huevos y carne
Si se usan argumentos nombrados en el mtodo str.format(), sus valores sern referidos usando el nombre del
argumento.
>>> print('Esta {comida} es {adjetivo}.'.format(
...
comida='carne', adjetivo='espantosa'))
otro='Georg'))
Se pueden usar '!a' (aplica apply()), '!s' (aplica str()) y '!r' (aplica repr()) para convertir el valor antes de
que se formatee.
>>> import math
>>> print('El valor de Pi es aproximadamente {}.'.format(math.pi))
El valor de Pi es aproximadamente 3.14159265359.
>>> print('El valor de Pi es aproximadamente {!r}.'.format(math.pi))
El valor de Pi es aproximadamente 3.141592653589793.
Un ': y especificador de formato opcionales pueden ir luego del nombre del campo. Esto aumenta el control sobre
cmo el valor es formateado. El siguiente ejemplo redondea Pi a tres lugares luego del punto decimal.
>>> import math
>>> print('El valor de PI es aproximadamente {0:.3f}.'.format(math.pi))
El valor de PI es aproximadamente 3.142.
Pasando un entero luego del ':' causar que que el campo sea de un mnimo nmero de caracteres de ancho. Esto
es til para hacer tablas lindas.
>>> tabla = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for nombre, telefono in tabla.items():
...
...
Dcab
==>
7678
Jack
==>
4098
Sjoerd
==>
4127
Si tens una cadena de formateo realmente larga que no quers separar, podra ser bueno que puedas hacer
referencia a las variables a ser formateadas por el nombre en vez de la posicin. Esto puede hacerse simplemente
pasando el diccionario y usando corchetes '[]' para acceder a las claves
>>> tabla = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
...
'Dcab: {0[Dcab]:d}'.format(tabla))
Esto se podra tambin hacer pasando la tabla como argumentos nombrados con la notacin **.
>>> tabla = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; '
'Dcab: {Dcab:d}'.format(**tabla))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
Esto es particularmente til en combinacin con la funcin integrada vars(), que devuelve un diccionario conteniendo
todas las variables locales.
Para una completa descripcin del formateo de cadenas con str.format(), mir en Tipos integrados.
El primer argumento es una cadena conteniendo el nombre de archivo. El segundo argumento es otra cadena
conteniendo unos pocos caracteres que describen la forma en que el archivo ser usado. El modo puede
ser 'r' cuando el archivo ser solamente ledo, 'w' para slo escribirlo (un archivo existente con el mismo nombre
ser borrado), y 'a' abre el archivo para agregarle informacin; cualquier dato escrito al archivo ser
automticamente agregado al final. 'r+' abre el archivo tanto para leerlo como para escribirlo. El argumento modo es
opcional; si se omite se asume 'r'.
Normalmente los archivos se abren en modo texto, lo que significa que pods leer y escribir cadenas del y al archivo,
las cuales se codifican utilizando un cdigo especfico. Si el cdigo no es especificado, el valor predeterminado
depende de la plataforma. Si se agrega b al modo el archivo se abre en modo binario: ahora los datos se leen y
escriben en forma de objetos bytes. Se debera usar este modo para todos los archivos que no contengan texto.
Cuando se lee en modo texto, por defecto se convierten los fines de lineas que son especficos a las plataformas
(\n en Unix, \r\n en Windows) a solamente \n. Cuando se escribe en modo texto, por defecto se convierten los \n a
los finales de linea especficos de la plataforma. Este cambio automtico est bien para archivos de texto, pero
corrompera datos binarios como los de archivos JPEG o EXE. Asegurate de usar modo binario cuando leas y escribas
tales archivos.
omite en la ltima linea del archivo si el mismo no termina en un fin de linea. Esto hace que el valor de retorno no sea
ambiguo; si f.readline() devuelve una cadena vaca, es que se alcanz el fin del archivo, mientras que una linea en
blanco es representada por '\n', una cadena conteniendo slo un nico fin de linea.
>>> f.readline()
'Esta es la primer linea del archivo.\n'
>>> f.readline()
'Segunda linea del archivo\n'
>>> f.readline()
''
Para leer lneas de un archivo, pods iterar sobre el objeto archivo. Esto es eficiente en memoria, rpido, y conduce a
un cdigo ms simple:
print(linea, end='')
Si quers leer todas las lneas de un archivo en una lista tambin pods usar list(f) o f.readlines().
f.write(cadena) escribe el contenido de la cadena al archivo, devolviendo la cantidad de caracteres escritos.
Para escribir algo ms que una cadena, necesita convertirse primero a una cadena:
>>> valor = ('la respuesta', 42)
>>> s = str(valor)
>>> f.write(s)
20
f.tell() devuelve un entero que indica la posicin actual en el archivo representada como nmero de bytes desde el
5
>>> f.read(1)
b'5'
>>> f.seek(-3, 2) # Va al tercer byte antes del final
13
>>> f.read(1)
b'd'
En los archivos de texto (aquellos que se abrieron sin una b en el modo), se permiten solamente desplazamientos
con seek relativos al comienzo (con la excepcin de ir justo al final con seek(0, 2)) y los nicos valores
de desplazamiento vlidos son aquellos retornados por f.tell(), o cero. Cualquier otro valor
de desplazamiento produce un comportamiento indefinido.
Cuando hayas terminado con un archivo, llam a f.close() para cerrarlo y liberar cualquier recurso del sistema
tomado por el archivo abierto. Luego de llamar f.close(), los intentos de usar el objeto archivo fallarn
automticamente.
>>> f.close()
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file
Es una buena prctica usar la declaracin with cuando manejamos objetos archivo. Tiene la ventaja que el archivo
es cerrado apropiadamente luego de que el bloque termina, incluso si se gener una excepcin. Tambin es mucho
ms corto que escribir los equivalentes bloques try-finally
>>> with open('archivodetrabajo', 'r') as f:
...
read_data = f.read()
>>> f.closed
True
Los objetos archivo tienen algunos mtodos ms, como isatty() y truncate() que son usados menos
frecuentemente; consult la Referencia de la Biblioteca para una gua completa sobre los objetos archivo.
Otra variante de la funcin dumps(), llamada dump(), simplemente serializa el objeto a un archivo de texto. As que,
si f es un objeto archivo de texto abierto para escritura, podemos hacer:
json.dump(x, f)
Para decodificar un objeto nuevamente, si f es un objeto archivo de texto que fue abierto para lectura:
x = json.load(x, f)
La simple tcnica de serializacin puede manejar listas y diccionarios, pero serializar instancias de clases arbitrarias
en JSON requiere un poco de esfuerzo extra. La referencia del mdulo json contiene una explicacin de esto.
Ver tambin
pickle - el mdulo pickle
Contrariamente a JSON, pickle es un protocolo que permite la serializacin de arbitrariamente objetos complejos de
Python. Por lo tanto, este es especfico de Python y no puede ser usado para comunicarse con aplicaciones escritas
en otros lenguajes. Es inseguro por defecto: deserializar datos que fueron serializados con pickle desde fuentes
inseguras puede ejecutar cdigo arbitrario, si los datos fueron interceptados por un atacante experto.
9. Errores y excepciones
Hasta ahora los mensajes de error no haban sido ms que mencionados, pero si probaste los ejemplos
probablemente hayas visto algunos. Hay (al menos) dos tipos diferentes de errores: errores de sintaxis y excepciones.
El intrprete repite la lnea culpable y muestra una pequea flecha que apunta al primer lugar donde se detect el
error. Este es causado por (o al menos detectado en) el smbolo que precede a la flecha: en el ejemplo, el error se
detecta en la funcin print(), ya que faltan dos puntos (':') antes del mismo. Se muestran el nombre del archivo y
el nmero de lnea para que sepas dnde mirar en caso de que la entrada venga de un programa.
9.2. Excepciones
Incluso si la declaracin o expresin es sintcticamente correcta, puede generar un error cuando se intenta ejecutarla.
Los errores detectados durante la ejecucin se llaman excepciones, y no son incondicionalmente fatales: pronto
aprenders cmo manejarlos en los programas en Python. Sin embargo, la mayora de las excepciones no son
manejadas por los programas, y resultan en mensajes de error como los mostrados aqu:
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: Can't convert 'int' object to str implicitly
La ltima lnea de los mensajes de error indica qu sucedi. Las excepciones vienen de distintos tipos, y el tipo se
imprime como parte del mensaje: los tipos en el ejemplo son: ZeroDivisionError, NameError y TypeError. La
cadena mostrada como tipo de la excepcin es el nombre de la excepcin predefinida que ocurri. Esto es verdad
para todas las excepciones predefinidas del intrprete, pero no necesita ser verdad para excepciones definidas por el
usuario (aunque es una convencin til). Los nombres de las excepciones estndar son identificadores incorporados
al intrprete (no son palabras clave reservadas).
El resto de la lnea provee un detalle basado en el tipo de la excepcin y qu la caus.
La parte anterior del mensaje de error muestra el contexto donde la excepcin sucedi, en la forma de un trazado del
error listando lneas fuente; sin embargo, no mostrar lneas ledas desde la entrada estndar.
try:
...
...
break
except ValueError:
...
...
...
Primero, se ejecuta el bloque try (el cdigo entre las declaracin try y except).
Si no ocurre ninguna excepcin, el bloque except se saltea y termina la ejecucin de la declaracin try.
Si ocurre una excepcin durante la ejecucin del bloque try, el resto del bloque se saltea. Luego, si su tipo
coincide con la excepcin nombrada luego de la palabra reservada except, se ejecuta el bloque except, y la
ejecucin contina luego de la declaracin try.
Si ocurre una excepcin que no coincide con la excepcin nombrada en el except, esta se pasa a
declaraciones try de ms afuera; si no se encuentra nada que la maneje, es una excepcin no manejada, y la
ejecucin se frena con un mensaje como los mostrados arriba.
Una declaracin try puede tener ms de un except, para especificar manejadores para distintas excepciones. A lo
sumo un manejador ser ejecutado. Slo se manejan excepciones que ocurren en el correspondiente try, no en otros
manejadores del mismo try. Un except puede nombrar mltiples excepciones usando parntesis, por ejemplo:
... except (RuntimeError, TypeError, NameError):
...
pass
El ltimo except puede omitir nombrar qu excepcin captura, para servir como comodn. Us esto con extremo
cuidado, ya que de esta manera es fcil ocultar un error real de programacin. Tambin puede usarse para mostrar un
mensaje de error y luego re-generar la excepcin (permitindole al que llama, manejar tambin la excepcin):
import sys
try:
f = open('miarchivo.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("Error OS: {0}".format(err))
except ValueError:
Las declaraciones try ... except tienen un bloque else opcional, el cual, cuando est presente, debe seguir a los
except. Es til para aquel cdigo que debe ejecutarse si el bloque try no genera una excepcin. Por ejemplo:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('no pude abrir', arg)
else:
print(arg, 'tiene', len(f.readlines()), 'lineas')
f.close()
El uso de else es mejor que agregar cdigo adicional en el try porque evita capturar accidentalmente una excepcin
que no fue generada por el cdigo que est protegido por la declaracin try ... except.
Cuando ocurre una excepcin, puede tener un valor asociado, tambin conocido como el argumento de la excepcin.
La presencia y el tipo de argumento depende del tipo de excepcin.
El except puede especificar una variable luego del nombre de excepcin. La variable se vincula a una instancia de
excepcin con los argumentos almacenados en instance.args. Por conveniencia, la instancia de excepcin
define __str__() para que se pueda mostrar los argumentos directamente, sin necesidad de hacer referencia
a .args. Tambin se puede instanciar la excepcin primero, antes de generarla, y agregarle los atributos que se
desee:
>>> try:
...
print(type(inst))
# la instancia de excepcin
...
print(inst.args)
...
print(inst)
...
...
x, y = inst
...
print('x =', x)
...
print('y =', y)
...
<class 'Exception'>
('carne', 'huevos')
('carne', 'huevos')
x = carne
y = huevos
# desempacar argumentos
Si una excepcin tiene argumentos, estos se imprimen como la ltima parte (el detalle) del mensaje para las
excepciones que no estn manejadas.
Los manejadores de excepciones no manejan solamente las excepciones que ocurren en el bloque try, tambin
manejan las excepciones que ocurren dentro de las funciones que se llaman (inclusive indirectamente) dentro
del bloque try. Por ejemplo:
>>> def esto_falla():
...
x = 1/0
...
>>> try:
...
esto_falla()
...
Manejando error en tiempo de ejecucin: int division or modulo by zero
El nico argumento a raise indica la excepcin a generarse. Tiene que ser o una instancia de excepcin, o una clase
de excepcin (una clase que hereda de Exception).
Si necesits determinar cuando una excepcin fue lanzada pero no quers manejarla, una forma simplificada de la
instruccin raise te permite relanzarla:
>>> try:
...
raise NameError('Hola')
...
raise
...
Vol una excepcin!
Traceback (most recent call last):
File "<stdin>", line 2, in ?
NameError: Hola
...
self.valor = valor
def __str__(self):
...
return repr(self.valor)
...
...
>>> try:
raise MiError(2*2)
...
...
...
En este ejemplo, el mtodo __init__() de Exception fue sobrescrito. El nuevo comportamiento simplemente crea
el atributo valor. Esto reemplaza el comportamiento por defecto de crear el atributo args.
Las clases de Excepciones pueden ser definidas de la misma forma que cualquier otra clase, pero usualmente se
mantienen simples, a menudo solo ofreciendo un nmero de atributos con informacin sobre el error que leern los
manejadores de la excepcin. Al crear un mdulo que puede lanzar varios errores distintos, una prctica comn es
crear una clase base para excepciones definidas en ese mdulo y extenderla para crear clases excepciones
especficas para distintas condiciones de error:
class Error(Exception):
"""Clase base para excepciones en el mdulo."""
pass
class EntradaError(Error):
"""Excepcin lanzada por errores en las entradas.
Atributos:
expresion -- expresin de entrada en la que ocurre el error
mensaje -- explicacin del error
"""
self.expresion = expresion
self.mensaje = mensaje
class TransicionError(Error):
"""Lanzada cuando una operacion intenta una transicion de estado no
permitida.
Atributos:
previo -- estado al principio de la transicin
siguiente -- nuevo estado intentado
mensaje -- explicacin de por qu la transicin no est permitida
"""
def __init__(self, previo, siguiente, mensaje):
self.previo = previo
self.siguiente = siguiente
self.mensaje = mensaje
La mayora de las excepciones son definidas con nombres que terminan en Error, similares a los nombres de las
excepciones estndar.
Muchos mdulos estndar definen sus propias excepciones para reportar errores que pueden ocurrir en funciones
propias. Se puede encontrar ms informacin sobre clases en el captulo Clases.
raise KeyboardInterrupt
... finally:
...
print('Chau, mundo!')
...
Chau, mundo!
KeyboardInterrupt
Traceback (most recent call last):
File "<stdin>", line 2, in ?
Una clusula finally siempre es ejecutada antes de salir de la declaracin try, ya sea que una excepcin haya
ocurrido o no. Cuando ocurre una excepcin en la clusula try y no fue manejada por una clusula except (o ocurri
en una clusula except o else), es relanzada luego de que se ejecuta la clusula finally. El finally es tambin
ejecutado a la salida cuando cualquier otra clusula de la declaracin try es dejada
viabreak, continue or return. Un ejemplo ms complicado:
>>> def dividir(x, y):
...
...
...
...
...
...
...
...
try:
result = x / y
except ZeroDivisionError:
print("divisin por cero!")
else:
print("el resultado es", result)
finally:
print("ejecutando la clausula finally")
...
>>> dividir(2, 1)
el resultado es 2.0
ejecutando la clausula finally
>>> dividir(2, 0)
divisin por cero!
ejecutando la clausula finally
>>> divide("2", "1")
ejecutando la clausula finally
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
Como pods ver, la clusula finally es ejecutada siempre. La excepcin TypeError lanzada al dividir dos cadenas
de texto no es manejado por la clusula except y por lo tanto es relanzada luego de que se ejecuta la
clusula finally.
En aplicaciones reales, la clusula finally es til para liberar recursos externos (como archivos o conexiones de
red), sin importar si el uso del recurso fue exitoso.
El problema con este cdigo es que deja el archivo abierto por un periodo de tiempo indeterminado luego de que esta
parte termine de ejecutarse. Esto no es un problema en scripts simples, pero puede ser un problema en aplicaciones
ms grandes. La declaracin with permite que objetos como archivos sean usados de una forma que asegure que
siempre se los libera rpido y en forma correcta.:
with open("miarchivo.txt") as f:
for linea in f:
print(linea, end="")
Luego de que la declaracin sea ejecutada, el archivo f siempre es cerrado, incluso si se encuentra un problema al
procesar las lneas. Objetos que, como los archivos, provean acciones de limpieza predefinidas lo indicarn en su
documentacin.
10. Clases
Comparado con otros lenguajes de programacin, el mecanismo de clases de Python agrega clases con un mnimo
de nuevas sintaxis y semnticas. Es una mezcla de los mecanismos de clases encontrados en C++ y Modula-3. Las
clases de Python proveen todas las caractersticas normales de la Programacin Orientada a Objetos: el mecanismo
de la herencia de clases permite mltiples clases base, una clase derivada puede sobreescribir cualquier mtodo de
su(s) clase(s) base, y un mtodo puede llamar al mtodo de la clase base con el mismo nombre. Los objetos pueden
tener una cantidad arbitraria de datos de cualquier tipo. Igual que con los mdulos, las clases participan de la
naturaleza dinmica de Python: se crean en tiempo de ejecucin, y pueden modificarse luego de la creacin.
En terminologa de C++, normalmente los miembros de las clases (incluyendo los miembros de datos),
son pblicos (excepto ver abajo Variables privadas), y todas las funciones miembro son virtuales. Como en Modula-3,
no hay atajos para hacer referencia a los miembros del objeto desde sus mtodos: la funcin mtodo se declara con
un primer argumento explcito que representa al objeto, el cual se provee implcitamente por la llamada. Como en
Smalltalk, las clases mismas son objetos. Esto provee una semntica para importar y renombrar. A diferencia de C++
y Modula-3, los tipos de datos integrados pueden usarse como clases base para que el usuario los extienda. Tambin,
como en C++ pero a diferencia de Modula-3, la mayora de los operadores integrados con sintaxis especial
(operadores aritmticos, de subndice, etc.) pueden ser redefinidos por instancias de la clase.
(Sin haber una terminologa universalmente aceptada sobre clases, har uso ocasional de trminos de Smalltalk y
C++. Usara trminos de Modula-3, ya que su semntica orientada a objetos es ms cercana a Python que C++, pero
no espero que muchos lectores hayan escuchado hablar de l).
Los atributos pueden ser de slo lectura, o de escritura. En el ltimo caso es posible la asignacin a atributos. Los
atributos de mdulo pueden escribirse: modulo.la_respuesta = 42. Los atributos de escritura se pueden borrar
tambin con la declaracin del. Por ejemplo,del modulo.la_respuesta va a eliminar el atributo la_respuesta del
objeto con nombre modulo.
Los espacios de nombres se crean en diferentes momentos y con diferentes tiempos de vida. El espacio de nombres
que contiene los nombres incluidos se crea cuando se inicia el intrprete, y nunca se borra. El espacio de nombres
global de un mdulo se crea cuando se lee la definicin de un mdulo; normalmente, los espacios de nombres de
mdulos tambin duran hasta que el intrprete finaliza. Las instrucciones ejecutadas en el nivel de llamadas superior
del intrprete, ya sea desde un script o interactivamente, se consideran parte del mdulo llamado __main__, por lo
tanto tienen su propio espacio de nombres global. (Los nombres incluidos en realidad tambin viven en un mdulo;
este se llama builtins.)
El espacio de nombres local a una funcin se crea cuando la funcin es llamada, y se elimina cuando la funcin
retorna o lanza una excepcin que no se maneje dentro de la funcin. (Podramos decir que lo que pasa en realidad
es que ese espacio de nombres se olvida.) Por supuesto, las llamadas recursivas tienen cada una su propio espacio
de nombres local.
Un mbito es una regin textual de un programa en Python donde un espacio de nombres es accesible directamente.
Accesible directamente significa que una referencia sin calificar a un nombre intenta encontrar dicho nombre dentro
del espacio de nombres.
Aunque los alcances se determinan estticamente, se usan dinmicamente. En cualquier momento durante la
ejecucin hay por lo menos cuatro alcances anidados cuyos espacios de nombres son directamente accesibles:
Si un nombre se declara como global, entonces todas las referencias y asignaciones al mismo van directo al mbito
intermedio que contiene los nombres globales del mdulo. Para reasignar nombres encontrados afuera del mbito
ms interno, se puede usar la declaracin nonlocal; si no se declara nonlocal, esas variables sern de slo lectura
(un intento de escribir a esas variables simplemente crea una nueva variable local en el mbito interno, dejando
intacta la variable externa del mismo nombre).
Habitualmente, el mbito local referencia los nombres locales de la funcin actual. Fuera de una funcin, el mbito
local referencia al mismo espacio de nombres que el mbito global: el espacio de nombres del mdulo. Las
definiciones de clases crean un espacio de nombres ms en el mbito local.
Es importante notar que los alcances se determinan textualmente: el mbito global de una funcin definida en un
mdulo es el espacio de nombres de ese mdulo, no importa desde dnde o con qu alias se llame a la funcin. Por
otro lado, la bsqueda de nombres se hace dinmicamente, en tiempo de ejecucin; sin embargo, la definicin del
lenguaje est evolucionando a hacer resolucin de nombres estticamente, en tiempo de compilacin, as que no te
confes de la resolucin de nombres dinmica! (De hecho, las variables locales ya se determinan estticamente.)
Una peculiaridad especial de Python es que, si no hay una declaracin global o nonlocal en efecto, las
asignaciones a nombres siempre van al mbito interno. Las asignaciones no copian datos, solamente asocian
nombres a objetos. Lo mismo cuando se borra: la declaracin del x quita la asociacin de x del espacio de nombres
referenciado por el mbito local. De hecho, todas las operaciones que introducen nuevos nombres usan el mbito
local: en particular, las instrucciones import y las definiciones de funciones asocian el mdulo o nombre de la funcin
al espacio de nombres en el mbito local.
La declaracin global puede usarse para indicar que ciertas variables viven en el mbito global y deberan
reasignarse all; la declaracinnonlocal indica que ciertas variables viven en un mbito encerrado y deberan
reasignarse all.
prueba_ambitos()
print("In global scope:", algo)
Las definiciones de clases, al igual que las definiciones de funciones (instrucciones def) deben ejecutarse antes de
que tengan efecto alguno. (Es concebible poner una definicin de clase dentro de una rama de un if, o dentro de una
funcin.)
En la prctica, las declaraciones dentro de una clase son definiciones de funciones, pero otras declaraciones son
permitidas, y a veces resultan tiles; veremos esto ms adelante. Las definiciones de funciones dentro de una clase
normalmente tienen una lista de argumentos peculiar, dictada por las convenciones de invocacin de mtodos; a esto
tambin lo veremos ms adelante.
Cuando se ingresa una definicin de clase, se crea un nuevo espacio de nombres, el cual se usa como mbito local;
por lo tanto, todas las asignaciones a variables locales van a este nuevo espacio de nombres. En particular, las
definiciones de funciones asocian el nombre de las funciones nuevas all.
Cuando una definicin de clase se finaliza normalmente se crea un objeto clase. Bsicamente, este objeto envuelve
los contenidos del espacio de nombres creado por la definicin de la clase; aprenderemos ms acerca de los objetos
clase en la seccin siguiente. El mbito local original (el que tena efecto justo antes de que ingrese la definicin de la
clase) es restablecido, y el objeto clase se asocia all al nombre que se le puso a la clase en el encabezado de su
definicin (Clase en el ejemplo).
...entonces MiClase.i y MiClase.f son referencias de atributos vlidas, que devuelven un entero y un objeto funcin
respectivamente. Los atributos de clase tambin pueden ser asignados, o sea que pods cambiar el valor
de MiClase.i mediante asignacin. __doc__ tambin es un atributo vlido, que devuelve la documentacin asociada
a la clase: "Simple clase de ejemplo".
La instanciacin de clases usa la notacin de funciones. Hac de cuenta que el objeto de clase es una funcin sin
parmetros que devuelve una nueva instancia de la clase. Por ejemplo (para la clase de ms arriba):
x = MiClase()
...crea una nueva instancia de la clase y asigna este objeto a la variable local x.
La operacin de instanciacin (llamar a un objeto clase) crea un objeto vaco. Muchas clases necesitan crear objetos
con instancias en un estado inicial particular. Por lo tanto una clase puede definir un mtodo especial
llamado __init__(), de esta forma:
def __init__(self):
self.datos = []
Cuando una clase define un mtodo __init__(), la instanciacin de la clase automticamente invoca
a __init__() para la instancia recin creada. Entonces, en este ejemplo, una instancia nueva e inicializada se puede
obtener haciendo:
x = MiClase()
Por supuesto, el mtodo __init__() puede tener argumentos para mayor flexibilidad. En ese caso, los argumentos
que se pasen al operador de instanciacin de la clase van a parar al mtodo __init__(). Por ejemplo,
>>> class Complejo:
...
...
self.r = partereal
...
self.i = parteimaginaria
...
>>> x = Complejo(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)
El otro tipo de atributo de instancia es el mtodo. Un mtodo es una funcin que pertenece a un objeto. En Python,
el trmino mtodo no est limitado a instancias de clase: otros tipos de objetos pueden tener mtodos tambin. Por
ejemplo, los objetos lista tienen mtodos llamados append, insert, remove, sort, y as sucesivamente. Pero, en la
siguiente explicacin, usaremos el trmino mtodo para referirnos exclusivamente a mtodos de objetos instancia de
clase, a menos que se especifique explcitamente lo contrario.
Los nombres vlidos de mtodos de un objeto instancia dependen de su clase. Por definicin, todos los atributos de
clase que son objetos funciones definen mtodos correspondientes de sus instancias. Entonces, en nuestro
ejemplo, x.f es una referencia a un mtodo vlido, dado queMiClase.f es una funcin, pero x.i no lo es, dado
que MiClase.i no lo es. Pero x.f no es la misma cosa que MiClase.f; es un objeto mtodo, no un objeto funcin.
En el ejemplo MiClase, esto devuelve la cadena 'hola mundo'. Pero no es necesario llamar al mtodo justo en ese
momento: x.f es un objeto mtodo, y puede ser guardado y llamado ms tarde. Por ejemplo:
xf = x.f
while True:
print(xf())
tipo = 'canino'
self.nombre = nombre
>>> d = Perro('Fido')
>>> e = Perro('Buddy')
>>> d.tipo
'canino'
>>> e.tipo
'canino'
>>> d.nombre
# nico para d
'Fido'
>>> e.nombre
# nico para e
'Buddy'
Como se vi en Unas palabras sobre nombres y objetos, los datos compartidos pueden tener efectos inesperados que
involucren objetos mutablescomo ser listas y diccionarios. Por ejemplo, la lista trucos en el siguiente cdigo no
debera ser usada como variable de clase porque una sola lista sera compartida por todos las instancias de Perro:
class Perro:
trucos = []
>>> d = Perro('Fido')
>>> e = Perro('Buddy')
>>> d.agregar_truco('girar')
>>> e.agregar_truco('hacerse el muerto')
>>> d.trucos
self.trucos.append(truco)
>>> d = Perro('Fido')
>>> e = Perro('Buddy')
>>> d.agregar_truco('girar')
>>> e.agregar_truco('hacerse el muerto')
>>> d.trucos
['girar']
>>> e.trucos
['hacerse el muerto']
class C:
f = f1
def g(self):
return 'hola mundo'
h = g
Ahora f, g y h son todos atributos de la clase C que hacen referencia a objetos funcin, y consecuentemente son todos
mtodos de las instancias de C; h siendo exactamente equivalente a g. Fijate que esta prctica normalmente slo sirve
para confundir al que lea un programa.
Los mtodos pueden llamar a otros mtodos de la instancia usando el argumento self:
class Bolsa:
def __init__(self):
self.datos = []
def agregar(self, x):
self.datos.append(x)
def dobleagregar(self, x):
self.agregar(x)
self.agregar(x)
Los mtodos pueden hacer referencia a nombres globales de la misma manera que lo hacen las funciones comunes.
El mbito global asociado a un mtodo es el mdulo que contiene su definicin. (Una clase nunca se usa como un
mbito global.) Si bien es raro encontrar una buena razn para usar datos globales en un mtodo, hay muchos usos
legtimos del mbito global: por lo menos, las funciones y mdulos importados en el mbito global pueden usarse por
los mtodos, al igual que las funciones y clases definidas en l. Habitualmente, la clase que contiene el mtodo est
definida en este mbito global, y en la siguiente seccin veremos algunas buenas razones por las que un mtodo
querra hacer referencia a su propia clase.
Todo valor es un objeto, y por lo tanto tiene una clase (tambin llamado su tipo). sta se almacena
como objeto.__class__.
10.5. Herencia
Por supuesto, una caracterstica del lenguaje no sera digna del nombre clase si no soportara herencia. La sintaxis
para una definicin de clase derivada se ve as:
class ClaseDerivada(ClaseBase):
<declaracin-1>
.
.
.
<declaracin-N>
El nombre ClaseBase debe estar definido en un mbito que contenga a la definicin de la clase derivada. En el lugar
del nombre de la clase base se permiten otras expresiones arbitrarias. Esto puede ser til, por ejemplo, cuando la
clase base est definida en otro mdulo:
class ClaseDerivada(modulo.ClaseBase):
La ejecucin de una definicin de clase derivada procede de la misma forma que una clase base. Cuando el objeto
clase se construye, se tiene en cuenta a la clase base. Esto se usa para resolver referencias a atributos: si un atributo
solicitado no se encuentra en la clase, la bsqueda contina por la clase base. Esta regla se aplica recursivamente si
la clase base misma deriva de alguna otra clase.
No hay nada en especial en la instanciacin de clases derivadas: ClaseDerivada() crea una nueva instancia de la
clase. Las referencias a mtodos se resuelven de la siguiente manera: se busca el atributo de clase correspondiente,
descendiendo por la cadena de clases base si es necesario, y la referencia al mtodo es vlida si se entrega un objeto
funcin.
Las clases derivadas pueden redefinir mtodos de su clase base. Como los mtodos no tienen privilegios especiales
cuando llaman a otros mtodos del mismo objeto, un mtodo de la clase base que llame a otro mtodo definido en la
misma clase base puede terminar llamando a un mtodo de la clase derivada que lo haya redefinido. (Para los
programadores de C++: en Python todos los mtodos son en efecto virtuales.)
Un mtodo redefinido en una clase derivada puede de hecho querer extender en vez de simplemente reemplazar al
mtodo de la clase base con el mismo nombre. Hay una manera simple de llamar al mtodo de la clase base
directamente: simplemente llams aClaseBase.metodo(self, argumentos). En ocasiones esto es til para los clientes
tambin. (Observ que esto slo funciona si la clase base es accesible como CalseBase en el mbito global.)
Python tiene dos funciones integradas que funcionan con herencia:
Us isinstance() para verificar el tipo de una instancia: isinstance(obj, int) devuelve True solo
si obj.__class__ es int o alguna clase derivada de int.
Us issubclass() para comprobar herencia de clase: issubclass(bool, int) da True ya que bool es una
subclase de int. Sin embargo,issubclass(float, int) devuelve False porque float no es una subclase
de int.
Para la mayora de los propsitos, en los casos ms simples, pods pensar en la bsqueda de los atributos heredados
de clases padres como primero en profundidad, de izquierda a derecha, sin repetir la misma clase cuando est dos
veces en la jerarqua. Por lo tanto, si un atributo no se encuentra en ClaseDerivada, se busca en Base1, luego
(recursivamente) en las clases base de Base1, y slo si no se encuentra all se lo busca enBase2, y as
sucesivamente.
En realidad es un poco ms complejo que eso; el orden de resolucin de mtodos cambia dinmicamente para
soportar las llamadas cooperativas a super(). Este enfoque es conocido en otros lenguajes con herencia mltiple
como llmese al siguiente mtodo y es ms poderoso que la llamada al superior que se encuentra en lenguajes con
slo herencia simple.
El ordenamiento dinmico es necesario porque todos los casos de herencia mltiple exhiben una o ms relaciones en
diamante (cuando se puede llegar al menos a una de las clases base por distintos caminos desde la clase de ms
abajo). Por ejemplo, todas las clases heredan de object, por lo tanto cualquier caso de herencia mltiple provee ms
de un camino para llegar a object. Para que las clases base no sean accedidas ms de una vez, el algoritmo
dinmico hace lineal el orden de bsqueda de manera que se preserve el orden de izquierda a derecha especificado
en cada clase, que se llame a cada clase base slo una vez, y que sea montona (lo cual significa que una clase
puede tener clases derivadas sin afectar el orden de precedencia de sus clases bases). En conjunto, estas
propiedades hacen posible disear clases confiables y extensibles con herencia mltiple. Para ms detalles
mir https://www.python.org/download/releases/2.3/mro/.
__actualizar = actualizar
class SubClaseMapeo(Mapeo):
Hay que aclarar que las reglas de modificacin de nombres estn diseadas principalmente para evitar accidentes; es
posible acceder o modificar una variable que es considerada como privada. Esto hasta puede resultar til en
circunstancias especiales, tales como en el depurador.
Notar que el cdigo pasado a exec o eval() no considera que el nombre de clase de la clase que invoca sea la clase
actual; esto es similar al efecto de la sentencia global, efecto que es de similar manera restringido a cdigo que es
compilado en conjunto. La misma restriccin aplica agetattr(), setattr() y delattr(), as como cuando se
referencia a __dict__ directamente.
10.7. Cambalache
A veces es til tener un tipo de datos similar al registro de Pascal o la estructura de C, que sirva para juntar
algunos pocos tems con nombre. Una definicin de clase vaca funcionar perfecto:
class Empleado:
pass
Algn cdigo Python que espera un tipo abstracto de datos en particular puede frecuentemente recibir en cambio una
clase que emula los mtodos de aquel tipo de datos. Por ejemplo, si tens una funcin que formatea algunos datos a
partir de un objeto archivo, pods definir una clase con mtodos read() y readline() que obtengan los datos de
alguna cadena en memoria intermedia, y pasarlo como argumento.
Los objetos mtodo de instancia tienen atributos tambin: m.__self__ es el objeto instancia con el mtodo m(),
y m.__func__ es el objeto funcin correspondiente al mtodo.
raise Instancia
En la primera forma, Clase debe ser una instancia de type o de una clase derivada de ella. La segunda forma es una
abreviatura de:
raise Clase()
Una clase en una clusula except es compatible con una excepcin si es de la misma clase o una clase base suya
(pero no al revs, una clusula except listando una clase derivada no es compatible con una clase base). Por ejemplo,
el siguiente cdigo imprimir B, C, D en ese orden:
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
Notar que si la clusulas except fueran invertidas (dejando except B al principio), habra impreso B, B, B; se dispara la
primera clusula exceptque coincide.
Cuando se imprime un mensaje de error para una excepcin sin atrapar, se imprime el nombre de la clase de la
excepcin, luego dos puntos y un espacio y finalmente la instancia convertida a un string usando la funcin
integrada str().
10.9. Iteradores
Es probable que hayas notado que la mayora de los objetos contenedores pueden ser recorridos usando una
sentencia for:
for elemento in [1, 2, 3]:
print(elemento)
for elemento in (1, 2, 3):
print(elemento)
for clave in {'uno':1, 'dos':2}:
print(clave)
for caracter in "123":
print(caracter)
for linea in open("miarchivo.txt"):
print(linea, end='')
Este estilo de acceso es limpio, conciso y conveniente. El uso de iteradores est impregnado y unifica a Python. En
bambalinas, la sentencia forllama a iter() en el objeto contenedor. La funcin devuelve un objeto iterador que
define el mtodo __next__() que accede elementos en el contenedor de a uno por vez. Cuando no hay ms
elementos, __next__() levanta una excepcin StopIteration que le avisa al bucle del for que hay que terminar.
Pods llamar al mtodo __next__() usando la funcin integrada __next__(); este ejemplo muestra como funciona
todo esto:
>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
next(it)
StopIteration
Habiendo visto la mecnica del protocolo de iteracin, es fcil agregar comportamiento de iterador a tus clases. Defin
un mtodo __iter__() que devuelva un objeto con un mtodo __next__(). Si la clase define __next__(),
entonces alcanza con que __iter__() devuelva self:
>>> class Reversa:
...
...
...
self.datos = datos
...
self.indice = len(datos)
...
def __iter__(self):
...
return self
...
def __next__(self):
...
if self.indice == 0:
raise StopIteration
...
...
self.indice = self.indice - 1
...
return self.datos[self.indice]
...
>>> rev = Reversa('spam')
>>> iter(rev)
<__main__.Reversa object at 0x00A1DB50>
>>> for char in rev:
...
...
m
a
p
print(char)
10.10. Generadores
Los generadores son una simple y poderosa herramienta para crear iteradores. Se escriben como funciones regulares
pero usan la sentenciayield cuando quieren devolver datos. Cada vez que se llama next() sobre l, el generador
contina desde donde dej (y recuerda todos los valores de datos y cual sentencia fue ejecutada ltima). Un ejemplo
muestra que los generadores pueden ser muy fciles de crear:
>>> def reversa(datos):
...
...
...
print(letra)
...
f
l
o
g
Todo lo que puede ser hecho con generadores tambin puede ser hecho con iteradores basados en clases, como se
describe en la seccin anterior. Lo que hace que los generadores sean tan compactos es que los
mtodos __iter__() y __next__() son creados automticamente.
Otra caracterstica clave es que las variables locales y el estado de la ejecucin son guardados automticamente
entre llamadas. Esto hace que la funcin sea ms fcil de escribir y quede mucho ms claro que hacerlo usando
variables de instancia tales como self.indice y self.datos.
Adems de la creacin automtica de mtodos y el guardar el estado del programa, cuando los generadores terminan
automticamente levantanStopIteration. Combinadas, estas caractersticas facilitan la creacin de iteradores, y
hacen que no sea ms esfuerzo que escribir una funcin regular.
# suma de cuadrados
# producto escalar
260
Footnotes
[1]
Excepto por un detalle. Los objetos mdulo tienen un atributo secreto de solo lectura llamado __dict__ que
devuelve el diccionario usado para implementar el espacio de nombres del mdulo; el nombre __dict__ es un
atributo, pero no es un nombre global. Obviamente, esto viola la abstraccin de la implementacin de espacios de
nombres, y debe ser restringido a cosas tales como depuradores post-mortem.
'C:\\Python35'
>>> os.chdir('/server/accesslogs')
>>> os.system('mkdir today')
Asegurate de usar el estilo import os en lugar de from os import *. Esto evitar que os.open() oculte a la funcin
integrada open(), que trabaja bastante diferente.
Las funciones integradas dir() y help() son tiles como ayudas interactivas para trabajar con mdulos grandes
como os:
>>> import os
>>> dir(os)
<devuelve una lista de todas las funciones del mdulo>
>>> help(os)
<devuelve un manual creado a partir de las documentaciones del mdulo>
Para tareas diarias de administracin de archivos y directorios, el mdulo shutil provee una interfaz de ms alto
nivel que es ms fcil de usar:
>>> import shutil
>>> shutil.copyfile('datos.db', 'archivo.db')
'archivo.db'
>>> shutil.move('/build/executables', 'dir_instalac')
'dir_instalac'
>>> print(sys.argv)
['demo.py', 'uno', 'dos', 'tres']
El mdulo getopt procesa sys.argv usando las convenciones de la funcin de Unix getopt(). El
mdulo argparse provee un procesamiento ms flexible de la linea de rdenes.
Cuando se necesita algo ms sencillo solamente, se prefieren los mtodos de las cadenas porque son ms fciles de
leer y depurar.
>>> 'te para tos'.replace('tos', 'dos')
'te para dos'
11.6. Matemtica
El mdulo math permite el acceso a las funciones de la biblioteca C subyacente para la matemtica de punto flotante:
>>> import math
>>> math.cos(math.pi / 4)
0.70710678118654757
>>> math.log(1024, 2)
10.0
# un float al azar
0.17970987693706186
>>> random.randrange(6)
El mdulo statistics calcula propiedades de estadstica bsica (la media, mediana, varianza, etc) de datos
nmericos:
>>> import statistics
>>> datos = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
>>> statistics.mean(datos)
1.6071428571428572
>>> statistics.median(datos)
1.25
>>> statistics.variance(datos)
1.3720238095238095
El proyecto SciPy <http://scipy.org> tiene muchos otros mdulos para clculos numricos.
...
line = line.decode('utf-8')
...
...
print(line)
... """)
>>> server.quit()
(Not que el segundo ejemplo necesita un servidor de correo corriendo en la mquina local)
En contraste con el fino nivel de granularidad del mdulo timeit, los mdulos profile y pstats proveen
herramientas para identificar secciones crticas de tiempo en bloques de cdigo ms grandes.
import doctest
doctest.testmod()
El mdulo unittest necesita ms esfuerzo que el mdulo doctest, pero permite que se mantenga en un archivo
separado un conjunto ms comprensivo de pruebas:
import unittest
class TestFuncionesEstadisticas(unittest.TestCase):
def test_promedio(self):
self.assertEqual(promedio([20, 30, 70]), 40.0)
self.assertEqual(round(promedio([1, 5, 7]), 1), 4.3)
with self.assertRaises(ZeroDivisionError):
promedio([])
with self.assertRaises(TypeError):
promedio(20, 30, 70)
Los mdulos xmlrpc.client y xmlrpc.server hacen que implementar llamadas a procedimientos remotos
sea una tarea trivial. A pesar de los nombres de los mdulos, no se necesita conocimiento directo o manejo de
XML.
El paquete email es una biblioteca para manejar mensajes de mail, incluyendo MIME y otros mensajes
basados en RFC 2822. Al contrario de smtplib y poplib que en realidad envan y reciben mensajes, el
paquete email tiene un conjunto de herramientas completo para construir y decodificar estructuras complejas
de mensajes (incluyendo adjuntos) y para implementar protocolos de cabecera y codificacin de Internet.
El paquete json provee soporte robusto para parsear este popular formato de intercambio de datos. El
mdulo csv soporta una lectura y escritura directa de archivos de valores separados por coma, comunmente
soportados por bases de datos y hojas de clculos. Procesar XML es soportado por los
paquetes xml.etree.ElementTree, xml.dom y xml.sax. Juntos, estos tres mdulos y paquetes simplifican
ampliamente el intercambio de datos entre aplicaciones Python y otras herramientas.
El mdulo sqlite3 es un wrapper para la librera de base de datos SQLite, proveyendo una base de datos
persistente que puede ser actualizada y accedida utilizando sintaxis SQL ligeramente no estndar.
Se soporta la internacionalizacin a travs de varios mdulos, incluyendo gettext, locale, y el
paquete codecs.
El mdulo pprint ofrece un control ms sofisticado de la forma en que se imprimen tanto los objetos predefinidos
como los objetos definidos por el usuario, de manera que sean legibles por el intrprete. Cuando el resultado ocupa
ms de una lnea, el generador de impresiones lindas agrega saltos de lnea y sangras para mostrar la estructura de
los datos ms claramente:
>>> import pprint
>>> t = [[[['negro', 'turquesa'], 'blanco', ['verde', 'rojo']], [['magenta',
...
'amarillo'], 'azul']]]
...
>>> pprint.pprint(t, width=30)
[[[['negro', 'turquesa'],
'blanco',
['verde', 'rojo']],
[['magenta', 'amarillo'],
'azul']]]
El mdulo textwrap formatea prrafos de texto para que quepan dentro de cierto ancho de pantalla:
>>> import textwrap
>>> doc = """El mtodo wrap() es como fill(), excepto que devuelve
... una lista de strings en lugar de una gran string con saltos de
... lnea como separadores."""
>>> print(textwrap.fill(doc, width=40))
El mtodo wrap() es como fill(), excepto
que devuelve una lista de strings en
lugar de una gran string con saltos de
lnea como separadores.
El mdulo locale accede a una base de datos de formatos especficos a una cultura. El atributo grouping de la
funcin format() permite una forma directa de formatear nmeros con separadores de grupo:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, '')
'Spanish_Argentina.1252'
>>> conv = locale.localeconv()
>>> x = 1234567.8
>>> locale.format("%d", x, grouping=True)
'1.234.567'
>>> locale.format_string("%s%.*f", (conv['currency_symbol'],
conv['frac_digits'], x), grouping=True)
...
'$1.234.567,80'
12.2. Plantillas
El mdulo string incluye una clase verstil Template (plantilla) con una sintaxis simplificada apta para ser editada
por usuarios finales. Esto permite que los usuarios personalicen sus aplicaciones sin necesidad de modificar la
aplicacin en s.
El formato usa marcadores cuyos nombres se forman con $ seguido de identificadores Python vlidos (caracteres
alfanumricos y guin de subrayado). Si se los encierra entre llaves, pueden seguir ms caracteres alfanumricos sin
necesidad de dejar espacios en blanco. $$ genera un$:
>>> from string import Template
>>> t = Template('${village}folk send $$10 to $cause.')
>>> t.substitute(village='Nottingham', cause='the ditch fund')
'Nottinghamfolk send $10 to the ditch fund.'
El mtodo substitute() lanza KeyError cuando no se suministra ningn valor para un marcador mediante un
diccionario o argumento por nombre. Para algunas aplicaciones los datos suministrados por el usuario puede ser
incompletos, y el mtodo safe_substitute() puede ser ms apropiado: deja los marcadores inalterados cuando
hay datos faltantes:
>>> t = Template('Return the $item to $owner.')
>>> d = dict(item='unladen swallow')
>>> t.substitute(d)
Traceback (most recent call last):
...
KeyError: 'owner'
>>> t.safe_substitute(d)
'Return the unladen swallow to $owner.'
Las subclases de Template pueden especificar un delimitador propio. Por ejemplo, una utilidad de renombrado por
lotes para un visualizador de fotos puede escoger usar signos de porcentaje para los marcadores tales como la fecha
actual, el nmero de secuencia de la imagen, o el formato de archivo:
>>> import time, os.path
>>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']
>>> class BatchRename(Template):
...
delimiter = '%'
...
>>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format):
Enter rename style (%d-date %n-seqnum %f-format):
>>> t = BatchRename(fmt)
Ashley_%n%f
')
...
...
...
img_1074.jpg --> Ashley_0.jpg
img_1076.jpg --> Ashley_1.jpg
img_1077.jpg --> Ashley_2.jpg
Las plantillas tambin pueden ser usadas para separar la lgica del programa de los detalles de mltiples formatos de
salida. Esto permite sustituir plantillas especficas para archivos XML, reportes en texto plano, y reportes web en
HTML.
inicio = 0
for i in range(3):
inicio += 14
campos = struct.unpack('<IIIHH', datos[inicio:inicio+16])
crc32, tam_comp, tam_descomp, tam_nomarch, tam_extra = fields
inicio += 16
nomarch = datos[inicio:inicio+tam_nomarch]
inicio += tam_nomarch
extra = datos[inicio:inicio+tam_extra]
print(nomarch, hex(crc32), tam_comp, tam_descomp)
12.4. Multi-hilos
La tcnica de multi-hilos (o multi-threading) permite desacoplar tareas que no tienen dependencia secuencial. Los
hilos se pueden usar para mejorar el grado de reaccin de las aplicaciones que aceptan entradas del usuario mientras
otras tareas se ejecutan en segundo plano. Un caso de uso relacionado es ejecutar E/S en paralelo con clculos en
otro hilo.
El cdigo siguiente muestra cmo el mdulo de alto nivel threading puede ejecutar tareas en segundo plano
mientras el programa principal contina su ejecucin:
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, arch_ent, arch_sal):
threading.Thread.__init__(self)
self.arch_ent = arch_ent
self.arch_sal = arch_sal
def run(self):
f = zipfile.ZipFile(self.arch_sal, 'w', zipfile.ZIP_DEFLATED)
f.write(self.arch_ent)
f.close()
print('Termin zip en segundo plano de: ', self.arch_ent)
seg_plano.join()
El desafo principal de las aplicaciones multi-hilo es la coordinacin entre los hilos que comparten datos u otros
recursos. A ese fin, el mdulo threading provee una serie de primitivas de sincronizacin que incluyen locks, eventos,
variables de condicin, y semforos.
An cuando esas herramientas son poderosas, pequeos errores de diseo pueden resultar en problemas difciles de
reproducir. La forma preferida de coordinar tareas es concentrar todos los accesos a un recurso en un nico hilo y
despus usar el mdulo queue para alimentar dicho hilo con pedidos desde otros hilos. Las aplicaciones que usan
objetos Queue para comunicacin y coordinacin entre hilos son ms fciles de disear, ms legibles, y ms
confiables.
12.5. Registrando
El mdulo logging ofrece un sistema de registros (logs) completo y flexible. En su forma ms simple, los mensajes
de registro se envan a un archivo o a sys.stderr:
import logging
logging.debug('Informacin de depuracin')
logging.info('Mensaje informativo')
logging.warning('Atencin: archivo de configuracin %s no se encuentra',
'server.conf')
logging.error('Ocurri un error')
logging.critical('Error crtico -- cerrando')
...
self.valor = valor
...
def __repr__(self):
...
return str(self.valor)
...
>>> a = A(10)
>>> d = weakref.WeakValueDictionary()
>>> d['primaria'] = a
>>> d['primaria']
10
>>> del a
>>> gc.collect()
0
>>> d['primaria']
El mdulo collections provee un objeto deque() que es como una lista ms rpida para agregar y quitar
elementos por el lado izquierdo pero con bsquedas ms lentas por el medio. Estos objetos son adecuados para
implementar colas y rboles de bsqueda a lo ancho:
>>> from collections import deque
>>> d = deque(["tarea1", "tarea2", "tarea3"])
>>> d.append("tarea4")
>>> print("Realizando", d.popleft())
Realizando tarea1
no_visitado = deque([nodo_inicial])
def busqueda_a_lo_ancho(no_visitado):
nodo = no_visitado.popleft()
for m in gen_moves(nodo):
if is_goal(m):
return m
no_visitado.append(m)
Adems de las implementaciones alternativas de listas, la biblioteca ofrece otras herramientas como el
mdulo bisect con funciones para manipular listas ordenadas:
>>> import bisect
>>> puntajes = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
El mdulo heapq provee funciones para implementar heaps basados en listas comunes. El menor valor ingresado se
mantiene en la posicin cero. Esto es til para aplicaciones que acceden a menudo al elemento ms chico pero no
quieren hacer un orden completo de la lista:
>>> from heapq import heapify, heappop, heappush
>>> datos = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
>>> heapify(datos)
# agregamos un elemento
aplicaciones financieras y para cualquier uso que requiera una representacin decimal exacta,
control de la precisin,
control del redondeo para satisfacer requerimientos legales o reglamentarios,
seguimiento de cifras significativas,
o para aplicaciones donde el usuario espera que los resultados coincidan con clculos hechos a mano.
Por ejemplo, calcular un impuesto del 5% de una tarifa telefnica de 70 centavos da resultados distintos con punto
flotante decimal y punto flotante binario. La diferencia se vuelve significativa si los resultados se redondean al centavo
ms prximo:
>>> from decimal import *
>>> round(Decimal('0.70') * Decimal('1.05'), 2)
Decimal('0.74')
>>> round(0.70 * 1.05, 2)
0.73
El resultado con Decimal conserva un cero al final, calculando automticamente cuatro cifras significativas a partir de
los multiplicandos con dos cifras significativas. Decimal reproduce la matemtica como se la hace a mano, y evita
problemas que pueden surgir cuando el punto flotante binario no puede representar exactamente cantidades
decimales.
La representacin exacta permite a la clase Decimal hacer clculos de modulo y pruebas de igualdad que son
inadecuadas para punto flotante binario:
>>> Decimal('1.00') % Decimal('.10')
Decimal('0.00')
>>> 1.00 % 0.10
0.09999999999999995
El mdulo decimal provee aritmtica con tanta precisin como haga falta:
>>> getcontext().prec = 36
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857')
Esto significa que tal vez no sea posible para una instalacin de Python cumplir los requerimientos de todas las
aplicaciones. Si la aplicacin A necesita la versin 1.0 de un mdulo particular y la aplicacin B necesita la versin 2.0,
entonces los requerimientos entran en conflicto e instalar la versin 1.0 o 2.0 dejar una de las aplicaciones sin
funcionar.
La solucin a este problema es crear un entorno virtual (comunmente abreviado como virtualenv), un directorio que
contiene una instalacin de Python de una versin en particular, adems de unos cuantos paquetes adicionales.
Diferentes aplicaciones pueden entonces usar entornos virtuales diferentes. Para resolver el ejemplo de
requerimientos en conflicto citado anteriormente, la aplicacin A puede tener su propio entorno virtual con la versin
1.0 instalada mientras que la aplicacin B tiene otro entorno virtual con la versin 2.0. Si la aplicacin B requiere que
actualizar la librera a la versin 3.0, sto no afectar el entorno virtual de la aplicacin A.
Esto crear la carpeta tutorial-env si no existe, y tambin crear las subcarpetas conteniendo la copia del intrprete
Python, la librera estndar y los archivos de soporte.
Una vez creado el entorno virtual, necesitars activarlo.
En Windows, ejecuta:
tutorial-env/Scripts/activate
(Este script est escrito para la consola bash. Si usas las consolas csh or fish, hay scripts
alternativos activate.csh y activate.fish que deber usar en su lugar).
Activar el entorno virtual cambiar el prompt de tu consola para mostrar que entorno virtual est usando, y modificar
el entorno para que al ejecutar python sea con esa versin e instalacin en particular. Por ejemplo:
-> source ~/envs/tutorial-env/bin/activate
(tutorial-env) -> python
Python 3.4.3+ (3.4:c7b9645a6f35+, May 22 2015, 09:31:25)
...
>>> import sys
>>> sys.path
['', '/usr/local/lib/python34.zip', ...,
'~/envs/tutorial-env/lib/python3.4/site-packages']
>>>
gary
novas
astroobs
PyAstronomy
...
pip tiene varios subcomandos: search, install, uninstall, freeze, etc. (consulta la gua Instalando mdulos de
Tambin se puede instalar una verisn especfica de un paquete ingresando el nombre del paquete seguido de == y el
nmero de versin:
-> pip install requests==2.6.0
Collecting requests==2.6.0
Using cached requests-2.6.0-py2.py3-none-any.whl
Installing collected packages: requests
Successfully installed requests-2.6.0
Si se re-ejecuta el comando, pip detectar que la versin ya est instalada y no har nada. Se puede ingresar un
nmero de versin diferente para instalarlo, o se puede ejecutar pip install --upgrade para actualizar el paquete a
la ltima versin:
-> pip install --upgrade requests
Collecting requests
Installing collected packages: requests
Found existing installation: requests 2.6.0
Uninstalling requests-2.6.0:
Successfully uninstalled requests-2.6.0
por pip install. Una convencin comn es poner esta lista en un archivo requirements.txt:
(tutorial-env) -> pip freeze > requirements.txt
(tutorial-env) -> cat requirements.txt
novas==3.1.1.3
numpy==1.9.2
requests==2.7.0
El archivo requirements.txt entonces puede ser agregado a nuestro control de versiones y distribudo como parte de
la aplicacin. Los usuarios pueden entonces instalar todos los paquetes necesarios con install -r:
-> pip install -r requirements.txt
Collecting novas==3.1.1.3 (from -r requirements.txt (line 1))
...
Collecting numpy==1.9.2 (from -r requirements.txt (line 2))
...
Collecting requests==2.7.0 (from -r requirements.txt (line 3))
...
Installing collected packages: novas, numpy, requests
Running setup.py install for novas
Successfully installed novas-3.1.1.3 numpy-1.9.2 requests-2.7.0
pip tiene muchas opciones ms. Consulta la gua Instalando mdulos de Python para la documentacin de pip.
Cuando hayas escrito un paquete y desees dejarlo disponible en Python Package Index, consulte la gua Glosario.
La referencia de la biblioteca:
Deberas hojear este manual, que tiene material de referencia completo (si bien breve) sobre tipos, funciones y
mdulos de la biblioteca estndar. La distribucin de Python estndar incluye un montn de cdigo adicional.
Hay mdulos para leer archivos de correo de Unix, obtener documentos va HTTP, generar nmeros
aleatorios, interpretar opciones de lnea de comandos, escribir programas CGI, comprimir datos, y muchas
otras tareas. Un vistazo por la Referencia de Biblioteca te dar una idea de lo que hay disponible.
Instalando mdulos de Python explica cmo instalar mdulos externos escritos por otros usuarios de Python.
La referencia del lenguaje: Una descripcin en detalle de la sintaxis y semntica de Python. Es una lectura
pesada, pero til como gua completa al lenguaje en si.
https://www.python.org: El sitio web principal sobre Python. Contiene cdigo, documentacin, y referencias a
pginas relacionadas con Python en la Web. Este sitio web tiene copias espejo en varios lugares del mundo
cmo Europa, Japn y Australia; una copia espejo puede funcionar ms rpido que el sitio principal,
dependiendo de tu ubicacin geogrfica.
https://docs.python.org: Acceso rpido a la documentacin de Python.
https://pypi.python.org: El ndice de Paquetes de Python, antes tambin apodado El Negocio de Quesos, es
un listado de mdulos de Python disponibles para descargar hechos por otros usuarios. Cundo comiences a
publicar cdigo, puedes registrarlo aqu as los dems pueden encontrarlo.
http://code.activestate.com/recipes/langs/python/: El Recetario de Python es una coleccin de tamao
considerable de ejemplos de cdigo, mdulos ms grandes, y programas tiles. Las contribuciones
particularmente notorias estn recolectadas en un libro tambin titulado Recetario de Python (OReilly &
Associates, ISBN 0-596-00797-3.)
http://www.pyvideo.org recolecta links de videos relacionados con Python de conferencias y reuniones de
grupos de usuarios.
http://scipy.org: El proyecto Python Cientfico incluye mdulos para manipulacin y clculo rpido de arreglos
adems de incluir paquetes para cosas como lgebra lineal, transformaciones de Fourier, soluciones no
lineales, distribuciones de nmeros al azar, anlisis estadsticos, y similares.
Para preguntas relacionadas con Python y reportes de problemas puedes escribir al grupo de
noticias comp.lang.python, o enviarlas a la lista de correo que hay en [email protected]. El grupo de noticias y la
lista de correo estn interconectadas, por lo que los mensajes enviados a uno sern retransmitidos al otro. Hay
alrededor de cientos de mensajes diarios (con picos de hasta varios cientos), haciendo (y respondiendo) preguntas,
sugiriendo nuevas caractersticas, y anunciando nuevos mdulos. Antes de escribir, asegrate de haber revisado la
lista de Preguntas Frecuentes (tambin llamado el FAQ). Muchas veces responde las preguntas que se hacen una y
otra vez, y quizz contega la solucin a tu problema.
Hay archivos de la lista de correo disponibles en https://mail.python.org/pipermail/. El FAQ responde a muchas de las
preguntas que aparecen una y otra vez, y puede que ya contenga la solucin a tu problema.
...tiene el valor 0/2 + 0/4 + 1/8. Estas dos fracciones tienen valores idnticos, la nica diferencia real es que la primera
est escrita en notacin fraccional en base 10 y la segunda en base 2.
Desafortunadamente, la mayora de las fracciones decimales no pueden representarse exactamente como fracciones
binarias. Como consecuencia, en general los nmeros de punto flotante decimal que ingress en la computadora son
slo aproximados por los nmeros de punto flotante binario que realmente se guardan en la mquina.
El problema es ms fcil de entender primero en base 10. Consider la fraccin 1/3. Pods aproximarla como una
fraccin de base 10
0.3
...o, mejor,
0.33
...o, mejor,
0.333
...y as. No importa cuantos dgitos desees escribir, el resultado nunca ser exactamente 1/3, pero ser una
aproximacin cada vez mejor de 1/3.
De la misma manera, no importa cuantos dgitos en base 2 quieras usar, el valor decimal 0.1 no puede representarse
exactamente como una fraccin en base 2. En base 2, 1/10 es la siguiente fraccin que se repite infinitamente:
0.0001100110011001100110011001100110011001100110011...
Fren en cualquier nmero finito de bits, y tendrs una aproximacin. En la mayora de las mquinas hoy en da, los
float se aproximan usando una fraccin binaria con el numerador usando los primeros 53 bits con el bit ms
significativos y el denominador como una potencia de dos. En el caso de 1/10, la fraccin binaria
es 3602879701896397 / 2 ** 55 que est cerca pero no es exactamente el valor verdadero de 1/10.
La mayora de los usuarios no son conscientes de esta aproximacin por la forma en que se muestran los valores.
Python solamente muestra una aproximacin decimal al valor verdadero decimal de la aproximacin binaria
almacenada por la mquina. En la mayora de las mquinas, si Python fuera a imprimir el verdadero valor decimal de
la aproximacin binaria almacenada para 0.1, debera mostrar
>>> 0.1
0.1000000000000000055511151231257827021181583404541015625
Esos son ms dgitos que lo que la mayora de la gente encuentra til, por lo que Python mantiene manejable la
cantidad de dgitos al mostrar en su lugar un valor redondeado
>>> 1 / 10
0.1
Slo record que, a pesar de que el valor mostrado resulta ser exactamente 1/10, el valor almacenado realmente es la
fraccin binaria ms cercana posible.
Interesantemente, hay varios nmeros decimales que comparten la misma fraccin binaria ms aproximada. Por
ejemplo, los nmeros 0.1,0.10000000000000001 y 0.1000000000000000055511151231257827021181583404541015625 son
todos aproximados por 3602879701896397 / 2 ** 55. Ya que todos estos valores decimales comparten la misma
aproximacin, se podra mostrar cualquiera de ellos para preservar el invarianteeval(repr(x)) == x.
Histricamente, el prompt de Python y la funcin integrada repr() eligieron el valor con los 17
dgitos, 0.10000000000000001. Desde Python 3.1, en la mayora de los sistemas Python ahora es capaz de elegir la
forma ms corta de ellos y mostrar 0.1.
Not que esta es la verdadera naturaleza del punto flotante binario: no es un error de Python, y tampoco es un error
en tu cdigo. Vers lo mismo en todos los lenguajes que soportan la aritmtica de punto flotante de tu hardware (a
pesar de que en algunos lenguajes por omisin no muestrenla diferencia, o no lo hagan en todos los modos de
salida).
Para una salida ms elegante, quizs quieras usar el formateo de cadenas de texto para generar un nmero limitado
de dgitos significativos:
>>> format(math.pi, '.12g')
# da 12 dgitos significativos
'3.14159265359'
'3.14'
>>> repr(math.pi)
'3.141592653589793'
Es importante darse cuenta que esto es, realmente, una ilusin: ests simplemente redondeando al mostrar el valor
verdadero de la mquina.
Una ilusin puede generar otra. Por ejemplo, ya que 0.1 no es exactamente 1/10, sumar tres veces 0.1 podra tambin
no generar exactamente 0.3:
>>> .1 + .1 + .1 == .3
False
Tambin, ya que 0.1 no puede acercarse ms al valor exacto de 1/10 y 0.3 no puede acercarse ms al valor exacto de
3/10, redondear primero con la funcin round() no puede ayudar:
>>> round(.1, 1) + round(.1, 1) + round(.1, 1) == round(.3, 1)
False
A pesar que los nmeros no pueden acercarse a los valores exactos que pretendemos, la funcin round() puede ser
til para redondear a posteriori, para que los resultados con valores inexactos se puedan comparar entre s:
>>> round(.1 + .1 + .1, 10) == round(.3, 10)
True
La aritmtica de punto flotante binaria tiene varias sorpresas como esta. El problema con 0.1 es explicado con
detalle abajo, en la seccin Error de Representacin. Mir los Peligros del Punto Flotante (en ingls, The Perils of
Floating Point) para una ms completa recopilacin de otras sorpresas normales.
Como dice cerca del final, no hay respuestas fciles. A pesar de eso, no le tengas mucho miedo al punto flotante!
Los errores en las operaciones flotantes de Python se heredan del hardware de punto flotante, y en la mayora de las
mquinas estn en el orden de no ms de una 1 parte en 2**53 por operacin. Eso es ms que adecuado para la
mayora de las tareas, pero necesits tener en cuenta que no es aritmtica decimal, y que cada operacin de punto
flotante sufre un nuevo error de redondeo.
A pesar de que existen casos patolgicos, para la mayora de usos casuales de la aritmtica de punto flotante al final
vers el resultado que espers si simplemente redondes lo que mostrs de tus resultados finales al nmero de
dgitos decimales que espers. str() es normalmente suficiente, y para un control ms fino mir los parmetros del
mtodo de formateo str.format() en Tipos integrados.
Para los casos de uso que necesitan una representacin decimal exacta, prob el mdulo decimal, que implementa
aritmtica decimal til para aplicaciones de contabilidad y de alta precisin.
El mdulo fractions soporta otra forma de aritmtica exacta, ya que implementa aritmtica basada en nmeros
racionales (por lo que nmeros como 1/3 pueden ser representados exactamente).
Si sos un usuario frecuente de las operaciones de punto flotante deberas pegarle una mirada al paquete Numerical
Python y otros paquetes para operaciones matemticas y estadsticas provistos por el proyecto SciPy. Mir
<http://scipy.org>.
Python provee herramientas que pueden ayudar en esas raras ocasiones cuando realmente quers saber el valor
exacto de un float. El mtodofloat.as_integer_ratio() expresa el valor del float como una fraccin:
>>> x = 3.14159
>>> x.as_integer_ratio()
(3537115888337719, 1125899906842624)
Ya que la fraccin es exacta, se puede usar para recrear sin prdidas el valor original:
>>> x == 3537115888337719 / 1125899906842624
True
El mtodo float.hex() expresa un float en hexadecimal (base 16), nuevamente devolviendo el valor exacto
almacenado por tu computadora:
>>> x.hex()
'0x1.921f9f01b866ep+1'
Esta representacin hexadecimal precisa se puede usar para reconstruir el valor exacto del float:
>>> x == float.fromhex('0x1.921f9f01b866ep+1')
True
Ya que la representacin es exacta, es til para portar valores a travs de diferentes versiones de Python de manera
confiable (independencia de plataformas) e intercambiar datos con otros lenguajes que soportan el mismo formato
(como Java y C99).
Otra herramienta til es la funcin math.fsum() que ayuda a mitigar la prdida de precisin durante la suma. Esta
funcin lleva la cuenta de dgitos perdidos mientras se suman los valores en un total. Eso puede hacer una
diferencia en la exactitud de lo que se va sumando para que los errores no se acumulen al punto en que afecten el
total final:
>>> sum([0.1] * 10) == 1.0
False
>>> math.fsum([0.1] * 10) == 1.0
True
...como
J ~= 2**N / 10
...y recordando que J tiene exactamente 53 bits (es >= 2**52 pero < 2**53), el mejor valor para N es 56:
>>> 2**52 <=
2**56 // 10
< 2**53
True
O sea, 56 es el nico valor para N que deja J con exactamente 53 bits. El mejor valor posible para J es entonces el
cociente redondeado:
>>> q, r = divmod(2**56, 10)
>>> r
6
Not que como lo redondeamos, esto es un poquito ms grande que 1/10; si no lo hubiramos redondeado, el
cociente hubiese sido un poquito menor que 1/10. Pero no hay caso en que sea exactamente 1/10!
Entonces la computadora nunca ve 1/10: lo que ve es la fraccin exacta de arriba, la mejor aproximacin al flotante
doble de 754 que puede obtener:
>>> 0.1 * 2 ** 55
3602879701896397.0
Si multiplicamos esa fraccin por 10**55, podemos ver el valor hasta los 55 dgitos decimales:
>>> 3602879701896397 * 10 ** 55 // 2 ** 55
1000000000000000055511151231257827021181583404541015625
...lo que significa que el valor exacto almacenado en la computadora es igual al valor decimal
0.1000000000000000055511151231257827021181583404541015625. En lugar de mostrar el valor decimal completo,
muchos lenguajes (incluyendo versiones ms viejas de Python), redondean el resultado a 17 dgitos significativos:
>>> format(0.1, '.17f')
'0.10000000000000001'
>>> Fraction.from_float(0.1)
Fraction(3602879701896397, 36028797018963968)
>>> (0.1).as_integer_ratio()
(3602879701896397, 36028797018963968)
>>> Decimal.from_float(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
Lo siguiente es una serie de enlaces que apuntan a la documentacin de Python que no est traducida.
Se incluye aqu slo a modo de referencia, y para hacer poder llegar fcil a la documentacin de cada tem cuando se
apunta al mismo en el tutorial.
ndice
ndice
ndice
Tipos de cadena
Mtodos de las cadenas
Formateo de cadenas
Antiguo formateo de cadenas
Tipos de mapeo
Tipos de secuencia
Tipos de nmeros complejos
Excepciones integradas
ndice
17.4.1. Expresiones
lambda
in
assert
break
continue
del
global
import
nonlocal
pass
raise
return
yield
for
if, elif, else
try, except, finally
while
with
def
ndice
17.6. Glosario
mutables
https://docs.python.org/3/glossary.html#term-mutable
archivo de texto
https://docs.python.org/3/glossary.html#term-text-file
entorno virtual
https://docs.python.org/3/glossary.html#term-virtual-environment
ndice
18. Apndice
18.1. Modo interactivo
18.1.1. Manejo de errores
Cuando ocurre un error, el intrprete imprime un mensaje de error y la traza del error. En el modo interactivo, luego
retorna al prompt primario; cuando la entrada viene de un archivo, el programa termina con cdigo de salida distinto a
cero luego de imprimir la traza del error. (Las excepciones manejadas por una clausula except en una
sentencia try no son errores en este contexto). Algunos errores son incondicionalmente fatales y causan una
terminacin con cdigo de salida distinto de cero; esto se debe a inconsistencias internas o a que el intrprete se
queda sin memoria. Todos los mensajes de error se escriben en el flujo de errores estndar; las salidas normales de
comandos ejecutados se escriben en la salida estndar.
Al ingresar el caracter de interrupcin (por lo general Control-C o Supr) en el prompt primario o secundario, se cancela
la entrada y retorna al prompt primario. [1] Tipear una interrupcin mientras un comando se estn ejecutando lanza la
excepcin KeyboardInterrupt, que puede ser manejada con una sentencia try.
...al principio del script y dndole al archivo permisos de ejecucin (asumiendo que el intrprete estn en la variable de
entorno PATH del usuario).#! deben ser los primeros dos caracteres del archivo. En algunas plataformas, la primera
lnea debe terminar al estilo Unix ('\n'), no como en Windows ('\r\n'). Not que el caracter numeral '#' se usa en
Python para comenzar un comentario.
Se le puede dar permisos de ejecucin al script usando el comando chmod:
.. code-block:: bash
$ chmod +x myscript.py
En sistemas Windows, no existe la nocin de modo ejecutable. El instalador de Python asocia automticamente la
extensin .py con python.exepara que al hacerle doble click a un archivo Python se corra el script. La extensin
tambin puede ser .pyw, en este caso se omite la ventana con la consola que normalmente aparece.
Si quers leer un archivo de inicio adicional desde el directorio actual, pods programarlo en el archivo de inicio global
usando algo comoif os.path.isfile('.pythonrc.py'): exec(open('.pythonrc.py').read()). Si quers usar el
archivo de inicio en un script, tens que hacer lo siguiente de forma explcita en el script:
import os
nombrearchivo = os.environ.get('PYTHONSTARTUP')
if nombrearchivo and os.path.isfile(nombrearchivo):
with open(nombrearchivo) as fobj:
archivo_inicio = fobj.read()
exec(archivo_inicio)
Ahora pods crear un archivo llamado usercustomize.py en ese directorio y poner lo que quieras en l. Eso afectar
cada ejecucin de Python, a menos que se arranque con la opcin -s para deshabilitar esta importacin automtica.
sitecustomize funciona de la misma manera, pero normalmente lo crea el administrador de la computadora en el
directorio global de paquetes para el sistema, y se importa antes que usercustomize. Para ms detalles, mir la
documentacin del mdulo site.
Footnotes
[1]