Python es el lenguaje de programaci´on que utilizaremos para las pr´acticas de la asignatura.
Algunas de las caracter´ısticas que lo hacen interesante para nosotros son:
Es f´acil de utilizar.
Es un lenguaje “completo”; no sirve s´olo para programar scripts.
Tiene gran variedad de estructuras de datos incorporadas al propio lenguaje.
Tiene una gran cantidad de bibliotecas (libraries).
Permite la programaci´on modular, orientada a objetos y su uso como un lenguaje imperativo
tradicional.
Es interpretado. Esto facilita el desarrollo (aunque ralentice la ejecuci´on).
Se puede utilizar desde un entorno interactivo.
Se puede extender f´acilmente.
Es muy expresivo: un programa Python ocupa mucho menos que su equivalente en C.
Este cuaderno pretende presentar los conceptos b´asicos de Python y capacitarte para comenzar
a utilizarlo. Esto no supone que todas las caracter´ısticas interesantes del lenguaje (ni siquiera todas
las ´utiles para la realizaci´on de las pr´acticas) hayan sido exhaustivamente recogidas aqu´ı.
1
La exposici´on de los conceptos b´asicos del lenguaje ocupa la mayor parte de este cuaderno,
intercalando en las explicaciones algunos ejercicios propuestos. Posteriormente, en la secci´on 11 se
propone un nuevo ejercicio, mucho m´as completo que los vistos hasta entonces. En el ap´endice A
se presentan soluciones a los ejercicios b´asicos. Finalmente, en el ap´endice B, puedes encontrar
(junto con las correspondientes respuestas) algunas de las preguntas m´as frecuentes de los alumnos
de cursos pasados.
2.Invocaci´on del int´erprete Python
Python suele estar instalado en /usr/local/bin o en /usr/bin,2as´ı que para invocar al
int´erprete interactivo basta con escribir
$ python
El sistema arrancar´a con un mensaje parecido a:
Python 2.4.3 (#1, May 24 2008, 13:47:28)
[GCC 4.1.2 20070626 (Red Hat 4.1.2-14)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
Esto nos permite empezar a trabajar (>>> es el prompt del int´erprete). Para salir del int´erprete
interactivo tenemos que pulsar Ctrl+D.
Si hemos almacenado un programa Python en un fichero (p.ej. fich.py), podemos ejecutarlo
con la orden
$ python fich.py
1
En http://www.python.org (as´ı como en http://marmota.dlsi.uji.es/python/, un mirror local) existe material suficiente como para resolver pr´acticamente cualquier duda que pueda surgir sobre Python.
2
Puedes averiguar d´onde est´a en tu m´aquina mediante la orden which python.
c
Universitat Jaume I 2009-2010
Page 6
6II26 Procesadores de lenguaje
Si nuestro sistema lo permite, tambi´en podemos ejecutar el programa directamente si, adem´as
de dar permisos de ejecuci´on al fichero, escribimos como primera l´ınea del fichero los caracteres
#! seguidos de la ruta completa del int´erprete Python. As´ı, si el int´erprete est´a en /usr/bin,
escribir´ıamos:
#!/usr/bin/python
Si el sistema est´a razonablemente bien instalado, tambi´en se puede utilizar:
#!/usr/bin/env python
Esto tiene la ventaja de que no depende de la situaci´on exacta de Python (env suele estar en
/usr/bin).
3.Tipos de datos
3.1.Tipos num´ericos
Es posible usar Python como una calculadora avanzada. Para ello, una vez arrancado el int´erprete, basta con escribir una expresi´on tras el prompt. El int´erprete calcular´a el resultado, lo
escribir´a y presentar´a un nuevo prompt. Por ejemplo3:
Python sigue las reglas habituales de precedencia y asociatividad; adem´as, el operador potencia
(**) es asociativo a derechas y m´as prioritario que el menos unario (-2**2 devuelve -4).
Para realizar operaciones l´ogicas tenemos los operadores and, or y not. Los valores que devuelven son:
El operador and devuelve su primer operando si este es falso y el segundo en caso contrario.
El operador or devuelve su primero operando si este es cierto y el segundo en caso contrario.
El operador not devuelve False si su operando es cierto y True si es falso.
Puede que te preguntes qu´e es cierto y qu´e es falso. Para Python, falso es (luego veremos estos
tipos con m´as detalle):
Todo lo dem´as es cierto. Las reglas pueden parecer liosas, pero en el contexto de las estructuras
de control funcionan como se espera de ellas y simplifican algunas tareas.
3
El s´ımbolo ^ representa el OR exclusivo y la funci´on oct genera la representaci´on octal de un n´umero.
Page 7
Introducci´on a Python7
Algunos ejemplos de expresiones l´ogicas:
>>> 2 and 4
4
>>> 0 and 4
0
>>> 2 or 4
2
>>> 0 or 4
4
>>> not 0
True
>>> not 4
False
>>> ’2’ and 4
4
>>> ’’ and 4
’’
Tambi´en disponemos de operadores sobre bits, que no debes confundir con los anteriores. El “y”
binario se representa con &, el “o” con |, el o-exclusivo con ^:
>>> 2 & 4
0
>>> 2 | 4
6
>>> 2 ^ 4
6
>>> 3 | 2
3
>>> 3 ^ 2
1
En cuanto a los tipos de los valores num´ericos, Python puede trabajar con enteros, enteros
largos (tienen una precisi´on ilimitada), flotantes y n´umeros complejos:
Existe un valor especial en Python para representar aquellos casos en los que “no hay valor”;
es el valor None. Este valor es el ´unico de su tipo. Se interpreta como falso en las expresiones
l´ogicas y es el devuelto por las funciones que no devuelven ning´un valor expl´ıcitamente. Cuando
el resultado de una expresi´on es None, el int´erprete no lo muestra:
>>> None
>>>
3.3.Cadenas
Python tambi´en trabaja con cadenas. Para escribirlas, hay que proporcionar una secuencia de
caracteres encerrada entre comillas simples o dobles. La elecci´on del delimitador s´olo afecta a c´omo
se escriben las comillas en la cadena: si el delimitador es una comilla doble, las comillas dobles se
escribir´an escap´andolas con una barra invertida (\); an´alogamente, si el delimitador es una comilla
sencilla, las comillas sencillas deber´an ir escapadas:
>>> "Quiero comprar un CD de Sinead O’Connor"
"Quiero comprar un CD de Sinead O’Connor"
>>> ’Quiero comprar un CD de Sinead O\’Connor’
"Quiero comprar un CD de Sinead O’Connor"
Como te habr´as imaginado, esto funciona porque la barra invertida es el car´acter de escape en
Python. Por eso, si queremos escribir una barra invertida, hay que escribirla dos veces (la orden
print hace que Python escriba el resultado de la expresi´on correspondiente)4:
>>> print "a\\b"
a\b
En el cuadro 1 puedes ver las secuencias de escape que admite Python. Las secuencias de escape
que no son reconocidas no se interpretan; la barra permanece:
>>> print "a\p"
a\p
4
Puedes estar pregunt´andote por qu´e incluimos aqu´ı la orden print y no lo hemos hecho en los ejemplos
anteriores. La raz´on es que el int´erprete escribe una representaci´on de la cadena que es a su vez una representaci´on
v´alida en Python para dicha cadena (la puedes utilizar como entrada al int´erprete). Sin embargo, print escribe la
propia cadena, si la entendemos como una secuencia de bytes. Si no acabas de ver la diferencia, prueba a teclear
los ejemplos con y sin print.
Page 9
Introducci´on a Python9
Cuadro 1: Secuencias de escape en las cadenas.
SecuenciaSignificado
\newlineNo se incluye en la cadena (sirve para escribir
literales de cadena que ocupen m´as de una l´ınea).
Si queremos evitar tener que escribir tantas barras, podemos utilizar las denominadas raw
strings. Simplemente, precede la cadena por una r y no se interpretar´an las secuencias de escape:
>>> print ’a\na’
a
>>> print r’a\na’
a\na
a
Ejercicio 1
Escribe una cadena que se imprima como ’\/".
Es posible operar con cadenas: + es la concatenaci´on, * la repetici´on y len devuelve la longitud
de una cadena:
>>> (’a’+"b")*3
’ababab’
>>> len("ab")
2
Un operador muy utilizado con las cadenas, especialmente para formatear la salida del programa, es %. Como operando izquierdo recibe una cadena con indicaciones de formato similares a las
de printf. El operando derecho es una expresi´on o una tupla. El resultado es la cadena resultante
de sustituir las marcas de formato en el operando izquierdo por el valor o valores del operando
derecho:
>>> a= 10
>>> "El resultado es %d" % a
’El resultado es 10’
>>> "%d-%d" % (3,6)
>>> "%d en hexadecimal es %x" % (123,123)
’123 en hexadecimal es 7b’
>>> "(%f)" % 3.4
’(3.400000)’
’3-6’
En el cuadro 2 puedes ver algunos de los caracteres de formato que se pueden emplear.
c
Universitat Jaume I 2009-2010
Page 10
10II26 Procesadores de lenguaje
Cuadro 2: Caracteres de formato para el operador % de cadenas.
Car´acterSignificado
d, iEntero en decimal.
oEntero en octal.
x, XEntero en hexadecimal.
e, EN´umero en coma flotante con exponente.
f, FN´umero en coma flotante sin exponente.
g, GN´umero en coma flotante con o sin exponente,
seg´un la precisi´on y la talla del exponente.
sTransforma el objeto en cadena usando str.
Tambi´en es posible aplicar determinados m´etodos sobre las cadenas5. Por ejemplo, si queremos
convertir la cadena a may´usculas o min´usculas podemos hacer:
>>> c="una cadena"
>>> c.upper()
>>> c.lower()
’una cadena’
’UNA CADENA’
Algunos de los m´etodos aplicables a cadenas son:
capitalize() devuelve una copia de la cadena con la primera letra en may´uscula.
center(n) devuelve una copia de la cadena centrada y con longitud n.
find(sub,[,desde[,hasta]]) devuelve la posici´on de la primera aparici´on de sub en la cadena; si
se incluye desde, la b´usqueda comienza en esa posici´on y termina en hasta, si se especifica.
isalnum() devuelve cierto si la cadena es no vac´ıa y s´olo contiene letras y d´ıgitos.
isalpha() devuelve cierto si la cadena es no vac´ıa y s´olo contiene letras.
isdigit() devuelve cierto si la cadena es no vac´ıa y s´olo contiene d´ıgitos.
islower() devuelve cierto si todas las letras de la cadena son min´usculas y hay al menos una
min´uscula.
isspace() devuelve cierto si la cadena es no vac´ıa y todos sus caracteres son espacios.
isupper() devuelve cierto si todas las letras de la cadena son may´usculas y hay al menos una
may´uscula.
lower()devuelve una copia de la cadena con las letras convertidas a min´usculas.
lstrip() devuelve una copia de la cadena con los blancos iniciales omitidos.
replace(v, n) devuelve una copia de la cadena donde se han sustituido todas las apariciones de
la cadena v por n.
rstrip() devuelve una copia de la cadena con los blancos finales omitidos.
split([s]) devuelve una lista que contiene las palabras de la cadena. Si se incluye la cadena s,
se utiliza como separador.
5
M´as adelante hablaremos con m´as detalle de los ob jetos: de momento, considera los m´etodos como funciones
con una “sintaxis peculiar”.
Page 11
Introducci´on a Python11
strip() devuelve una copia de la cadena con los blancos iniciales y finales omitidos.
upper() devuelve una copia de la cadena convertida a may´usculas.
3.4.Subsecuencias
Las cadenas son simplemente un tipo especial de secuencias (otro son las listas, que veremos
luego). Todas las secuencias pueden ser “troceadas” utilizando la notaci´on de slices:
>>> c="cadena"
>>> c[3]
’e’
>>> c[3:5]
’en’
Si entre los corchetes s´olo hay un n´umero positivo, se devuelve el elemento de la posici´on
correspondiente (se cuenta desde cero). Cuando hay dos n´umeros, se devuelve la subsecuencia
que comienza en el primero y llega hasta antes del ´ultimo. Los n´umeros negativos se consideran
posiciones desde el final de la secuencia. Una manera de ver c´omo se elige el subintervalo es la
siguiente. Imagina que las posiciones corresponden a marcas entre los caracteres:
012 3456
cad ena
-6 -5 -4 -3 -2 -1
Para saber qu´e se obtiene con c[i:j], basta con mirar entre las marcas correspondientes a i y j .
Si se omite i, se asume que es cero; si se omite j, se asume que es la longitud de la cadena:
>>> c="cadena"
>>> c[:3]
’cad’
Una propiedad que es ´util saber es que c[:i]+c[i:] es igual a c.
Ejercicio 2
Asigna a una variable la cadena esto es un ejemplo, y haz que se escriba por pantalla la
cadena un ejemplo es esto utilizando la notaci´on de slices.
>>> c[-1]
’a’
>>> c[2:-2]
’de’
>>> c[3:]
’ena’
3.5.Listas
Las listas son secuencias de elementos de cualquier tipo separados por comas. Para escribirlas
se utiliza una secuencia de expresiones separadas por comas entre corchetes:
>>> s=[1,1+1,6/2]
>>> s
[1, 2, 3]
Mediante la notaci´on para subsecuencias, es posible acceder a elementos individuales de la lista o
partes de ella:
>>> s=[1,2,3]
>>> s[1]
2
>>> s[1:-1]
[2]
c
Universitat Jaume I 2009-2010
>>> s[0]=s[2]
>>> s[2]=s[1]/2
>>> s
[3, 2, 1]
Page 12
12II26 Procesadores de lenguaje
F´ıjate en dos cosas importantes. No es lo mismo una lista de un elemento que el elemento solo6.
Adem´as, podemos asignar nuevos valores a partes de la lista, tanto a elementos individuales como
a subsecuencias:
Observa que no es necesario que las cadenas origen y destino de la asignaci´on tengan la misma
longitud; esto se puede emplear para borrar partes de la lista asign´andoles la lista vac´ıa (que se
representa mediante []).
Como las cadenas, las listas tienen las operaciones +, * y len():
>>> s=[1,2]
>>> s*3
[1, 2, 1, 2, 1, 2]
[1, 2, 1, 2]
>>> len(s)
2
>>> s+s
Hemos dicho que los elementos de las listas pueden tener cualquier tipo; en particular, pueden
ser listas:
Jugando un poco, podemos hacer que una lista se contenga a s´ı misma. Python trabaja c´omodamente con este tipo de estructuras:
>>> a= [1,2]
>>> a[1]=a
>>> a
[1, [...]]
Ejercicio 3
>>> a[1]
[1, [...]]
>>> a[0]
1
>>> a[1][0]
1
Convierte la lista a=[1,[2,[3,4]],5] en [1,[2,[3, 4],[6,7]], 5].
Las listas son objetos, as´ı que se pueden invocar m´etodos sobre ellas:
>>> a=[1,4,3]
>>> a.sort()
>>> a
[1, 3, 4]
Algunos m´etodos ´utiles son:
insert(i,x) inserta el elemento x en la posici´on i (despu´es de la inserci´on, x ocupar´a la posici´on i).
append(x) a˜nade el elemento x al final de la lista (a.append(x)es equivalente a a.insert(len(a),x)).
index(x) devuelve el ´ındice del primer elemento de la lista igual a x.
6
A diferencia de lo que sucede con las cadenas, ya que un car´acter no es sino una cadena de longitud 1.
Page 13
Introducci´on a Python13
remove(x) elimina el primer elemento de la lista igual a x.
sort() ordena los elementos de la lista.
reverse() invierte el orden de los elementos de la lista.
count(x) cuenta el n´umero de veces que x aparece en la lista.
Para eliminar elementos de la lista dando su posici´on en lugar de su valor, se puede utilizar
del:
>>> a=[1,2,3,4,5]
>>> del a[2]
>>> a
>>> del a[1:3]
>>> a
[1, 5]
[1, 2, 4, 5]
Tambi´en se puede utilizar del para eliminar variables completas:
>>> x=7
>>> x
7
>>> del x
>>> x
Traceback (most recent call last):
File "<stdio>", line 1, in <module>
NameError: name ’x’ is not defined
Ten cuidado con lo siguiente: al asignar un objeto compuesto a una variable, no se hace una
copia, simplemente se almacena una referencia. Esto puede llevar a resultados no deseados. Por
ejemplo:
>>> a=[1,2,3]
>>> b=a
>>> a
[1, 2, 1]
>>> b[2]=1
Esto tambi´en pasa al utilizar variables para crear objetos mayores:
>>> b=[1,2]
>>> c=[b,b]
>>> c
>>> b[0]=2
>>> c
[[2, 2], [2, 2]]
[[1, 2], [1, 2]]
Sin embargo:
>>> b=[1,2]
>>> c=[b,b]
>>> c
>>> b=[3]
>>> c
[[1, 2], [1, 2]]
[[1, 2], [1, 2]]
Ejercicio 4
¿Puedes explicar lo que pasa en el segundo caso?
3.6.Tuplas
Las tuplas son secuencias inmutables de objetos, el que no puedan modificarse hace que se
puedan tratar de una manera m´as eficiente. Como en el caso de las listas, estos objetos pueden ser
c
Universitat Jaume I 2009-2010
Page 14
14II26 Procesadores de lenguaje
de cualquier tipo, pero no pueden modificarse:
>>> a=(1,2,3)
>>> a[1:3]
(2, 3)
>>> a[1]=9
Traceback (most recent call last):
File "<stdio>", line 1, in <module>
TypeError: ’tuple’ object does not support item assignment
Las tuplas se crean mediante una lista de elementos separados por comas y encerrados entre
par´entesis. Esto crea el problema de c´omo especificar tuplas de un solo elemento. Para ello basta
con escribir el elemento seguido de una coma:
>>> a=3,
>>> a
(3,)
3.7.Diccionarios
Python permite utilizar diccionarios (tambi´en llamados vectores asociativos). Estos funcionan
como vectores normales en los que los ´ındices pueden ser cualquier tipo de objeto inmutable
(n´umeros, cadenas y tuplas cuyos componentes sean inmutables). Esto es especialmente ´util para
aquellos casos en los que la informaci´on se indexa de forma natural mediante cadenas.
El diccionario vac´ıo se crea mediante {}. Para a˜nadir elementos basta con hacer las correspondientes asignaciones. Despu´es se puede recuperar cualquier elemento a partir de la clave:
Es un error intentar recuperar la informaci´on a partir de una clave que no est´e en el diccionario.
Para evitarlo, se puede utilizar el m´etodo has_key(), que devuelve True si la clave est´a y False
en caso contrario. Adem´as, puedes utilizar el m´etodo keys() para obtener la lista de claves del
diccionario.
>>> tel.has_key("pepe")
True
Otra alternativa es utilizar get. Este m´etodo recibe dos par´ametros: el primero es la clave que
se va a buscar y el segundo el valor que se devolver´a en caso de que no se encuentre. Si no se
especifica el segundo par´ametro, el valor devuelto al no encontrar la clave es None.
Como ya has visto, al utilizar Python en modo interactivo, los resultados se muestran directamente por pantalla. Sin embargo, al utilizar Python para interpretar un fichero, es necesario
indicarle expl´ıcitamente que muestre el resultado. Para ello, disponemos de la orden print. Para
Page 15
Introducci´on a Python15
utilizarla, se escribe print seguido de aquello que queremos mostrar por pantalla. En caso de que
sea m´as de una expresi´on, estas se separan mediante comas (que provocar´an la aparici´on de los
correspondientes espacios):
>>> print 2+3, 4+5
5 9
Si no queremos que se a˜nada un salto de l´ınea, basta con terminar la orden con una coma.
Podemos emplear el operador % para formatear la salida de manera c´omoda:
>>> n=4
>>> m=0.5
>>> print "Resumen: %d datos, media %g." % (n, m)
Resumen: 4 datos, media 0.5.
Para crear un objeto de tipo fichero, se emplea open. Normalmente se emplea con dos argumentos: el nombre del fichero y el modo con que se abre (por ejemplo, "r" para leer y "w" para
escribir). Una vez creado un objeto de tipo fichero (llam´emosle f), se pueden emplear sobre ´el los
siguientes m´etodos:
f.read() lee todo el fichero y lo devuelve en forma de cadena. Si se especifica una talla, leer´a
como mucho ese n´umero de bytes. Si se ha alcanzado el fin del fichero, devuelve la cadena
vac´ıa.
f.readline() lee una l´ınea del fichero y la devuelve en forma de cadena, dejando un car´acter fin
de l´ınea al final, a menos que la ´ultima l´ınea del fichero no termine en nueva l´ınea. Si se ha
alcanzado el fin del fichero, devuelve la cadena vac´ıa.
f.readlines() llama a f.readline() repetidamente y devuelve una lista que contiene todas las
l´ıneas del fichero.
f.write(s) escribe la cadena s en el fichero. Devuelve None.
f.close() cierra el fichero.
Existen otros m´etodos para los ficheros como tell, seek, isatty o truncate. Consulta el
manual (Python Library Reference, Built-in Types, File Objects) si necesitas usarlos.
5.Control de flujo
Hasta ahora, el orden de ejecuci´on de las sentencias era secuencial. En Python es posible
especificar ´ordenes distintos mediante estructuras de control de flujo.
5.1.Sangrado
A diferencia de otros lenguajes, en Python no hay marcas expl´ıcitas para se˜nalar el comienzo
y fin de un bloque de sentencias. Para ello se utiliza el sangrado (indentation ). ¡Cuidado al copiar
programas! La idea b´asica es que todas las sentencias que forman un bloque subordinado a una
construcci´on tienen un sangrado m´as profundo que la primera l´ınea de la construcci´on a la que
pertenecen. Antes de un bloque de sentencias que necesitan un nuevo nivel de sangrado, suele
aparecer un car´acter dos puntos.
As´ı, las sentencias que se ejecutan cuando la condici´on de un if es cierta est´an “a la derecha”
con respecto a ese if. El bloque termina cuando el sangrado es el mismo que el de la construcci´on
o menor, o, en el int´erprete interactivo, cuando hay una l´ınea en blanco (dentro de un fichero se
pueden dejar l´ıneas en blanco sin afectar al significado del programa).
Para hacer el sangrado se pueden emplear indistintamente espacios en blanco o caracteres de
tabulaci´on en cualquier n´umero (siempre que este n´umero sea el mismo dentro de l´ıneas que est´en
“al mismo nivel” de anidamiento).
c
Universitat Jaume I 2009-2010
Page 16
16II26 Procesadores de lenguaje
5.2.Ejecuci´on condicional
La estructura de control m´as simple es la construcci´on if. Como es habitual en otros lenguajes
de programaci´on, la sentencia if tiene asociada una condici´on y una serie de instrucciones que se
ejecutar´an en caso de cumplirse aqu´ella.
Por ejemplo:
>>> i=5
>>> if i>4:
...print "Mayor"
...
Mayor
Los tres puntos son el prompt secundario: recuerdan que estamos en un nuevo nivel de anidamiento.
Como otros lenguajes, Python ofrece la posibilidad de completar el if con un else, pero
adem´as tiene la abreviatura elif que equivale a un else seguido de un if:
>>> i=5
>>> if i>4:
...print "Mayor"
... elif i==4:
...print "Igual"
... else:
...print "Menor"
...
Mayor
La condici´on puede ser cualquier expresi´on. Para decidir si el resultado es cierto, se siguen las
mismas reglas que comentamos en la secci´on 3.1 para los operadores l´ogicos:
La construcci´on for permite iterar sobre los valores de una secuencia:
>>> a=[’primero’,’segundo’,’tercero’]
>>> for i in a:
...print i,
...
primero segundo tercero
Con frecuencia es interesante que una variable tome los valores desde el cero hasta un n´umero
dado. Para esto, se puede utilizar la funci´on range que devuelve una lista que comienza en cero y
termina en el n´umero anterior al que se le pasa como par´ametro:
>>> range(4)
[0, 1, 2, 3]
Si se le pasan dos par´ametros, a y b, la lista que se construye va desde a hasta b − 1. Si se le pasan
tres par´ametros, a, b y c, la lista va desde a hasta b (sin alcanzarla) en saltos de c (que puede ser
negativo):
En ocasiones, queremos saber tanto el elemento como el ´ındice sobre el que estamos iterando.
Podemos hacerlo mediante enumerate:
>>> a="hola"
>>> for pos,c in enumerate(a):
...print pos,c
...
0 h
1 o
2 l
3 a
Como en C, es posible salir de un bucle mediante break y pasar a la iteraci´on siguiente con
continue:
>>> a=[1,2,4,0,3]
>>> for i in a:
...if i==0:
...break
...print i,
...
1 2 4
Ejercicio 5
Escribe un programa que utilice un bucle para crear una lista con los n´umeros del 1 al 10 y
luego la muestre por pantalla.
Ejercicio 6
Escribe un programa que, a partir de una tupla cualquiera, obtenga una lista con todos los
elementos de la tupla. Utiliza un bucle.
Ejercicio 7
Escribe un programa que muestre por pantalla los n´umeros m´ultiplos de 7 entre el 1 y el 1000.
Utiliza range(1001) en un bucle for con los if necesarios. Despu´es haz lo mismo empleando un
range con tres par´ametros.
>>> for i in a:
...if i== 0:
...continue
...print i,
...
1 2 4 3
6.Funciones
Python permite definir funciones con una sintaxis muy sencilla: tras la palabra reservada def
se escribe el nombre de la funci´on, el nombre de los par´ametros entre par´entesis y dos puntos. Las
l´ıneas que se encuentran a continuaci´on formar´an el cuerpo de la funci´on. Por ejemplo, si en el
fichero fibonacci.py tenemos:
#!/usr/bin/env python
def fib(n): # N´umeros de Fibonacci
a,b=0,1
r=[] # r tendr´a el resultado
while b<n:
r.append(b)
a,b=b,a+b
return r
print fib(10)
Page 19
Introducci´on a Python19
Al ejecutarlo obtenemos [1, 1, 2, 3, 5, 8]. En este ejemplo podemos ver varias cosas interesantes. En primer lugar, que los comentarios comienzan por el s´ımbolo # y terminan al finalizar la
l´ınea. Por otro lado, vemos que se pueden utilizar variables dentro de la funci´on. Estas variables
son locales, a menos que se declaren expl´ıcitamente como globales (con global). Por ejemplo, el
siguiente programa escribe 4 3:
a,b =2,3
def algo():
global a
a,b=4,4
algo()
print a,b
Por otro lado, los par´ametros se pasan por referencia a objeto. En la pr´actica, esto quiere decir
que los par´ametros de tipo elemental (num´erico o cadena), se pasan por valor:
Sin embargo, si el par´ametro tiene un tipo compuesto, se pasa por algo similar a referencia:
>>> def cambia(n):
...n[1]=2
...
>>> cambia(a)
>>> print a
[3, 2, 3]
>>> a=[3,3,3]
Esto es equivalente a lo que pasa con la asignaci´on de variables (recuerda lo que se coment´o
en la secci´on 3.5).
Ejercicio 8
Reescribe el programa del ejercicio 7 utilizando una funci´on a la que se le pase un n´umero y
devuelva True si es m´ultiplo de 7, o False si no lo es.
6.1.Un ejemplo
Vamos a utilizar los conceptos anteriores para crear un ´arbol binario de b´usqueda. Como ya
sabes, un ´arbol binario de b´usqueda es un ´arbol en el que todos los elementos situados en el
sub´arbol izquierdo de un nodo son menores (en un cierto orden) que el situado en ese nodo y
todos los del sub´arbol derecho son mayores (no permitiremos repeticiones).
Como representaci´on utilizaremos tuplas de tres elementos: el primer elemento ser´a el sub´arbol
izquierdo, el segundo la informaci´on del nodo y el tercero el sub´arbol derecho. Para el ´arbol vac´ıo
utilizaremos None.
Crear un ´arbol es sencillo:
def crea_arbol():
return None
c
Universitat Jaume I 2009-2010
Page 20
20II26 Procesadores de lenguaje
Para insertar un elemento, hacemos una b´usqueda binaria:
def inserta(A,c):
if A==None: #´Arbol vac´ıo
return (None,c,None)
elif c<A[1]: # Almacenarlo a la izquierda
return (inserta(A[0],c),A[1],A[2])
elif c>A[1]: # Almacenarlo a la derecha
return (A[0],A[1],inserta(A[2],c))
else:
return A
Comprobar si un elemento pertenece al ´arbol es trivial:
A= inserta(A,"diminuto")
print A
print pertenece(A,"´ınfimo")
print pertenece(A,"grande")
6.2.Par´ametros con valores por defecto
Es posible escribir funciones con par´ametros que tienen determinados valores cuando no se
especifican en la llamada (valores por defecto). Para ello se escribe, tras el nombre del par´ametro,
el valor que tiene cuando no aparece en la llamada. Por ejemplo:
def convierte(n,base=10):
if n==0:
return [0]
elif n<0:
n=-n
neg=True
else:
neg=False
r= []
while n>0:
r.append(n % base)
n=n/base
if neg:
r.append(’-’)
r.reverse()
return r
La llamada convierte(123) devuelve [1,2,3] mientras que la llamada convierte(123,8)
devuelve [1,7,3].
Page 21
Introducci´on a Python21
6.3.Algunas funciones predefinidas
En esta secci´on veremos algunas de las funciones predefinidas en Python.
abs(x) valor absoluto.
chr(i) devuelve una cadena de un solo car´acter: aqu´el cuyo c´odigo ASCII es i.
cmp(x,y) compara x e y, devolviendo 0 si son iguales, un valor negativo si x < y y un valor
positivo si x > y.
eval(s) eval´ua s interpret´andola como una expresi´on Python.
filter(f,l) devuelve una lista formada por los elementos de la lista l que hacen que f devuelva
cierto.
float(x) convierte un n´umero entero a coma flotante.
hex(x) devuelve una cadena con la representaci´on en hexadecimal del entero x.
int(x) convierte un n´umero o una cadena en entero.
len(s) devuelve la longitud de la secuencia s.
long(x) convierte un n´umero o una cadena en entero largo.
max(s) devuelve el m´aximo de la secuencia s.
min(s) devuelve el m´ınimo de la secuencia s.
oct(x) devuelve una cadena con la representaci´on en octal del entero x.
open(f[,m[,b]]) devuelve un objeto de tipo fichero ligado al fichero de nombre f (una cadena).
El modo de apertura se indica mediante m, que puede ser: "r" para lectura (valor por
defecto), "w" para escritura, "r+" para lectura y escritura y "a" para escritura al final del
fichero. Si se incluye, b determina el tipo de buffer que se utilizar´a: 0, sin buffer ; 1, con buffer
de l´ınea; y cualquier otro valor indica un buffer de (aproximadamente) ese tama˜no.
ord(c) devuelve el c´odigo ASCII del car´acter c.
pow(x,y) equivale a x**y.
range([a,]b[,c]) devuelve la lista [a, a + c, a + 2c, ... ]. El valor por omisi´on de a es 0, el
de c es 1. Si c es positivo, el ´ultimo elemento de la lista es el mayor a + ci que es menor
que b; si c es negativo, el ´ultimo elemento de la lista es el menor a + ci que es mayor que b.
Con dos argumentos, se supone que el omitido es c.
repr(v) devuelve una cadena r (la representaci´on de v) tal que eval(r) sea igual a v.
str(v) devuelve una cadena r que representa a v de manera “legible” pero que puede no ser
aceptable para eval.
tuple(s) devuelve una tupla construida con los elementos de la secuencia s.
type(v) devuelve el tipo de v.
xrange([a,]b[,c]) tiene el mismo efecto que range al usarlo en un bucle, pero no crea una lista
en memoria.
c
Universitat Jaume I 2009-2010
Page 22
22II26 Procesadores de lenguaje
7.Bibliotecas
Una de las ventajas de Python es la gran cantidad de objetos y funciones que hay disponibles
en forma de bibliotecas (o m´odulos). Para acceder a las funciones de una biblioteca, tenemos varias
opciones:
1. Importar el m´odulo en cuesti´on y despu´es acceder a la funci´on mediante el nombre de la
biblioteca. As´ı, para utilizar la funci´on sin, que est´a en math, har´ıamos:
import math
print math.sin(2.0)
2. Importar la funci´on del m´odulo y utilizarla directamente:
from math import sin
print sin(2.0)
3. Importar todas las funciones del m´odulo y utilizarlas directamente:
from math import *
print sin(2.0)
Es aconsejable hacer esto ´unicamente si sabemos que el m´odulo est´a preparado para ello, en otro
caso, puede haber problemas.
Si queremos importar varios m´odulos en una sola sentencia, podemos separarlos por comas:
import sys, math, re
Algunas de las bibliotecas que pueden ser ´utiles para la asignatura son:
sysda acceso a variables del int´erprete y a funciones que interact´uan con ´el.
typesdefine nombres para los tipos de objetos del int´erprete.
stringoperaciones sobre cadenas.
reexpresiones regulares.
mathfunciones matem´aticas.
tempfilecreaci´on de ficheros temporales.
7.1.La biblioteca sys
exit(n) aborta la ejecuci´on y devuelve el valor n a la shell.
argv lista de los argumentos que se le pasan al programa.
Ejemplo: el siguiente programa escribe los argumentos con los que se le llama:
import sys
for i in sys.argv:
print i
stdin, stdout, stderr objetos de tipo fichero que corresponden a la entrada est´andar, salida
est´andar y salida de error. Sobre ellos pueden invocarse los m´etodos explicados en la secci´on 4.
Page 23
Introducci´on a Python23
7.2.La biblioteca types
Define nombres para los tipos que proporciona el int´erprete. Por ejemplo: NoneType, para el
tipo de None; IntType, para el tipo entero; LongType, para el tipo entero largo; FloatType, el tipo
real; etc.
La siguiente funci´on recibe como par´ametros una lista y un segundo par´ametro. Si este par´ametro es un entero, borra de la lista el elemento de la posici´on correspondiente; si no es entero,
elimina el primer elemento igual a ´el:
from types import *
def delete(list, item):
if type(item) is IntType:
del list[item]
else:
list.remove(item)
7.3.La biblioteca string
Esta biblioteca define diversas variables y funciones ´utiles para manipular cadenas. Muchas de
sus funciones han sido sustituidas por m´etodos sobre las cadenas.
Entre las variables tenemos:
digits’0123456789’.
hexdigits’0123456789abcdefABCDEF’.
lettersLetras min´usculas y may´usculas.
lowercaseLetras min´usculas.
octdigits’01234567’.
uppercaseLetras may´usculas.
whitespaceBlancos (espacio, tabuladores horizontal y vertical,
retorno de carro, nueva l´ınea y nueva p´agina)
En cuanto a las funciones:
atof(s) convierte la cadena s en un flotante.
atoi(s,[b]) convierte la cadena s en un entero (en base b si se especifica).
atol(s,[b]) convierte la cadena s en un entero largo (en base b si se especifica).
lower(s) pasa s a min´usculas.
join(l[,p]) devuelve la cadena que se obtiene al unir los elementos de la lista l separados por
blancos o por p si se especifica.
split(s[,p]) devuelve la lista que se obtiene al separar la cadena s por los blancos o por p si se
especifica.
strip(s) devuelve la cadena que se obtiene al eliminar de s sus blancos iniciales y finales.
upper(s) pasa s a may´usculas.
Ejemplo: la siguiente funci´on recibe como par´ametros una cadena y un entero y devuelve la
palabra indicada por el entero pasada a may´usculas:
def mayus(c,i):
l=string.split(c)
return string.upper(l[i])
c
Universitat Jaume I 2009-2010
Page 24
24II26 Procesadores de lenguaje
7.4.La biblioteca re
Esta biblioteca define las funciones adecuadas para trabajar con expresiones regulares. Un
aviso: existen otras dos bibliotecas (regex y regsub) con la misma utilidad, sin embargo est´an
siendo abandonadas (son “obsolescentes”).
En el cuadro 3(a) puedes ver algunos de los elementos que se pueden emplear para escribir
expresiones regulares.
El car´acter barra invertida tiene un significado especial dentro de las expresiones regulares. Si el
car´acter siguiente es uno de los de la tabla anterior, este pierde su significado y pasa a representarse
a s´ı mismo (as´ı \+ representa el car´acter + en lugar de una o m´as barras). En el cuadro 3(b) puedes
ver el significado de algunas secuencias de escape.
A la hora de escribir expresiones regulares hay que tener en cuenta lo que se coment´o en la
secci´on 3.3 acerca de los caracteres de escape. As´ı, para conseguir \d hay que escribir "\\d" y
para conseguir una barra, hay que escribir ¡cuatro!. Por eso merece la pena utilizar raw strings.
Entre las funciones que ofrece este m´odulo, tenemos:
match(p,s) devuelve una instancia de MatchObject si cero o m´as caracteres del comienzo de s
concuerdan con la expresi´on regular p. En caso contrario devuelve None.
search(p,s) devuelve una instancia de MatchObject si cero o m´as caracteres de s (no necesa-
riamente del principio) concuerdan con la expresi´on regular p. En caso contrario devuelve
None.
compile(p) devuelve una versi´on compilada de p. Esto es ´util si se va a utilizar la misma expresi´on
muchas veces. Sobre el objeto resultante es posible llamar a los m´etodos match y search con
el mismo significado que antes. Por ejemplo:
>>> import re
>>> id=re.compile("[a-zA-Z][a-zA-Z0-9]*")
>>> if id.match("var23"):
...print "s´ı"
... else:
...print "no"
...
s´ı
>>>
Los objetos de la clase MatchObject (los que se devuelven si las b´usquedas tienen ´exito) guardan
los “grupos referenciables” que se han encontrado. Para recuperarlos se utiliza el siguiente m´etodo:
group(n) devuelve el valor del n-´esimo grupo referenciable.
Adem´as de comprobar si un determinado texto aparece en la cadena, se pueden hacer sustituciones de texto y dividir la cadena mediante expresiones regulares utilizando las siguientes
funciones:
sub(p, r, s) sustituye en la cadena s las apariciones de la expresi´on regular p (que puede estar
compilada) por la cadena r.
split(p,s) tiene la misma funci´on que string.split pero permite utilizar una expresi´on regular
(que puede estar compilada) como separador.
Page 25
Introducci´on a Python25
Cuadro 3: Algunos componentes de las expresiones regulares.
(a) Operadores:
Explicaci´onEjemplo
.Cualquier car´acter excepto el de nueva
l´ınea.
^Comienzo de cadena.^a..Cadena que empieza por a, tiene tres
$Fin de cadena.a..$Cadena que empieza por a, tiene tres
|Disyunci´on.a|bLa letra a o la b.
*Clausura de la expresi´on de su izquierda.a*Cero o m´as aes.
+Clausura positiva de la expresi´on de su
izquierda.
?Opcionalidad de la expresi´on de la izquier-
da.
{m,n} Entre m y n repeticiones de la expresi´on
a su izquierda.
[]Conjunto de caracteres. Los caracteres
pueden enumerarse uno a uno o utilizar
un guion (-) entre dos caracteres para
expresar la idea de rango. Si quiere
incluirse en el conjunto el car´acter ], este
ha de ser el primero de la enumeraci´on,
y lo mismo sucede con - (o se pueden
utilizar las notaciones \] y \- en cualquier
posici´on). Si el primer car´acter es ^, se
considera el complementario del conjunto
de caracteres enumerados.
()Cambia el orden de aplicaci´on de las expre-
siones. Adem´as, crea un “grupo referenciable”.
a.bCadena de tres caracteres que empieza por
a y termina por b.
caracteres y est´a al comienzo.
caracteres y est´a al final.
a+Una o m´as aes.
a?Una o cero aes.
a{3,5} Entre tres y cinco aes.
[ac2-5] Una a, una c, un 2, un 3, un 4 o un 5.
(a|b)+ Una secuencia de una o m´as aes y bes.
(b) Secuencias de escape:
SecuenciaSignificado
\\Corresponde al propio car´acter barra invertida.
\nRepresenta al “grupo referenciable” con el n´umero n. Por ejemplo: (.+)-\1 incluye a
la cadena 11-11 pero no a 12-21.
\bCadena vac´ıa al final de una palabra. Las palabras son secuencias de caracteres
alfanum´ericos que tienen “pegadas” dos cadenas vac´ıas.
\BUna cadena vac´ıa pero que no est´a ni al principio ni al final de una palabra.
\sEspacios en blanco, equivale a [ \t\n\r\f\v]
\SEl complementario del anterior.
\dD´ıgitos, equivale a [0-9].
\DNo d´ıgitos, equivale a [^0-9].
\wCaracteres que pueden estar en una palabra, equivale a [a-zA-Z0-9_].
\WComplementario del anterior.
c
Universitat Jaume I 2009-2010
Page 26
26II26 Procesadores de lenguaje
7.5.La biblioteca math
Define una serie de funciones matem´aticas id´enticas a las de la librer´ıa est´andar de C:
Define una funci´on para facilitar la creaci´on de ficheros temporales:
mktemp() devuelve un nombre de fichero temporal ´unico, garantizando que ning´un otro fichero se
llama as´ı.
Tambi´en define la variable tempdir que tiene una cadena con la ruta del directorio en el que se
crear´an los ficheros. En un sistema UNIX, si tempdir vale None, se obtiene el valor del directorio
de la variable de entorno TEMPDIR.
8.Escritura de m´odulos
Tambi´en es posible para el usuario escribir sus propias bibliotecas o m´odulos. Por ejemplo,
podemos crear un fichero circulos.py que contenga lo siguiente:
import math
pi2=math.pi*2
def perimetro(radio):
return pi2*radio
def area(radio):
return pi*radio*radio
Ahora podemos utilizar tanto la nueva variable como las dos funciones en nuestros programas.
Para eso debemos incluir la sentencia import circulos. Despu´es accederemos a la variable y las
funciones mediante circulos.pi2, circulos.perimetro y circulos.area.
Al importar un m´odulo, Python lo “precompila”, dejando el resultado en un fichero con el
mismo nombre que el m´odulo y extensi´on .pyc. Si este m´odulo ya existiera y tuviera una fecha
de modificaci´on posterior al .py, la precompilaci´on no se habr´ıa producido y el m´odulo se habr´ıa
cargado directamente.
En muchas ocasiones es ´util hacer que un m´odulo act´ue como programa. Por ejemplo, durante
el desarrollo de un m´odulo se puede incluir c´odigo para probarlo. Para facilitar esto, se puede utilizar la construcci´on if __name__=="__main__": e incluirse despu´es el c´odigo de prueba. Puedes
encontrar un ejemplo de esto en la secci´on 10.6.
Page 27
Introducci´on a Python27
9.Excepciones
Cuando hay un error de ejecuci´on, Python emite lo que se llama una excepci´on. Por ejemplo:
ZeroDivisionError: integer division or modulo by zero
El mensaje indica que se ha producido una excepci´on y su tipo. Adem´as indica en qu´e fichero se
ha producido y da una traza de las llamadas. Esto es muy ´util para depurar programas.
Si queremos controlar las excepciones, podemos hacerlo mediante la construcci´on try-except.
El significado de la construcci´on es el siguiente. Se ejecutan las sentencias asociadas a la parte try
hasta que finalicen normalmente o se produzca alguna excepci´on. En el primer caso, la ejecuci´on
contin´ua en la sentencia siguiente al try-except. En caso de que se produzca una excepci´on, se
interrumpe la ejecuci´on. Si la excepci´on coincide con la que se indica en el except, la ejecuci´on
contin´ua en las sentencias asociadas a ´el. Por ejemplo:
>>> l=[2,0,10,12,0.0,8]
>>> for i in l:
...try:
...print i,1.0/i
...except ZeroDivisionError:
...print i,’no tiene inversa’
...
Si no se asocia ninguna excepci´on al except, este las capturar´a todas, lo que no es aconsejable
ya que puede enmascarar errores que no se tratan adecuadamente. Las excepciones tambi´en pueden
tener un valor asociado en el que se den detalles adicionales. Para capturarlo, basta con poner una
variable detr´as del tipo de excepci´on:
>>> try:
...a=1/0
... except ZeroDivisionError,a:
...print a
...
integer division or modulo by zero
Los programas tambi´en pueden generar las excepciones expl´ıcitamente mediante la orden
raise. Se le pasan uno o dos argumentos. El primero es el tipo de excepci´on, el segundo indica los detalles:
>>> raise ZeroDivisionError,"esta es voluntaria"
Traceback (most recent call last):
File "<stdio>", line 1, in <module>
ZeroDivisionError: esta es voluntaria
2 0.5
0 0 no tiene inversa
10 0.1
12 0.0833333333333
File "<stdio>", line 2, in <module>
TypeError: exceptions must be classes or instances, not str
>>> raise miexc, "es la m´ıa"
Traceback (most recent call last):
File "<stdio>", line 1, in <module>
TypeError: exceptions must be classes or instances, not str
Otra posibilidad, que es la recomendada, es crear una clase (veremos las clases en el siguiente
punto) derivada de Exception:
>>> class MiExcepcion (Exception):
...# El m´etodo __init__ sirve
...# como constructor:
...def __init__(self, mensaje):
...self.mensaje= mensaje
...
>>> try:
...raise MiExcepcion("Esto lo he lanzado yo")
... except MiExcepcion, excepcion:
...print excepcion.mensaje
...
Esto lo he lanzado yo
10.Clases y objetos
Como se coment´o en la introducci´on, Python es un lenguaje orientado a objetos. Adem´as, la
complicaci´on sint´actica para esto es m´ınima. Haciendo una simplificaci´on tal vez excesiva, podemos
entender la clase como una especie de “registro” cuyas instancias adem´as de los campos habituales
(que contienen datos como enteros o listas) pueden tener campos que son funciones. Por ejemplo,
podr´ıamos tener un objeto del tipo veh´ıculo. Este objeto tendr´ıa un campo (pos) que ser´ıa su
posici´on. Adem´as tendr´ıa dos m´etodos: mueve que cambia la posici´on a˜nadiendo los kil´ometros
que se pasan como par´ametros y posicion que devuelve la posicion actual. Un ejemplo de uso
ser´ıa:
Lo primero que hacemos es crear una instancia de la clase veh´ıculo. Despu´es aplicamos los
m´etodos sobre el veh´ıculo para cambiar su posici´on. Podemos imaginarnos que al aplicar un m´etodo
sobre un objeto, el m´etodo en cuesti´on “sabe” sobre qu´e objeto se est´a aplicando. Esto se hace
pasando al m´etodo un par´ametro adicional: el propio objeto.
Para definir la clase anterior har´ıamos lo siguiente:
>>> v.mueve(14)
>>> print v.posicion()
24
class vehiculo:
def __init__(self):
self.pos=0
def mueve(self,k):
Page 29
Introducci´on a Python29
self.pos=self.pos+k
def posicion(self):
return self.pos
Podemos destacar lo siguiente:
Para definir una clase, basta con poner su nombre tras la palabra reservada class y lo que
sigue forma parte de la definici´on de la clase (hasta la primera l´ınea que tenga el mismo nivel
de indentaci´on que la l´ınea donde est´a class).
Generalmente, la definici´on de la clase consiste en una serie de funciones que ser´an los
m´etodos de la clase.
Todos los m´etodos tienen self como primer par´ametro. Este es el par´ametro con el que se
pasa el objeto. El nombre self es convencional, puede ser cualquier otro.
Existe un m´etodo especial __init__. A este m´etodo se le llama cuando se crea un objeto de
la clase.
Los atributos (campos de datos) de la clase se crean como las variables de Python, mediante
una asignaci´on sin declaraci´on previa.
El m´etodo __init__ puede tener par´ametros adicionales. En este caso, se pasan con el nombre
de la clase. Por ejemplo, si quisi´eramos dar una posici´on inicial para el veh´ıculo har´ıamos:
def __init__(self,pos):
self.pos=pos
Y para crear un objeto en la posici´on 10, la llamada ser´ıa v=vehiculo(10). Si combinamos esto
con los par´ametros por defecto, podemos hacer que si no se especifica posici´on, el veh´ıculo comience
en 0 y, en caso contrario, donde se especifique:
def __init__(self,pos=0):
self.pos=pos
10.1.M´etodos especiales
Hemos visto que __init__ es un m´etodo que se invoca impl´ıcitamente al crear un objeto.
Existen otros m´etodos que tambi´en se invocan de forma impl´ıcita en determinadas circunstancias.
Todos ellos tienen nombres rodeados por __. Vamos a estudiar algunos de ellos.
Creaci´on y destrucci´on de los objetos
__init__(self[, args]) es el m´etodo que se llama al crear instancias de la clase. Los argumentos
opcionales se pasan como par´ametros al nombre de la clase.
__del__(self) se llama al destruir un objeto.
Representaci´on de los objetos como cadenas
__str__(self) se llama al utilizar sobre el objeto la funci´on predefinida str, al aplicarle la orden
print o con la marca de formato %s. Debe devolver como resultado una cadena.
__repr__(self) se llama, por ejemplo, al utilizar sobre el objeto la funci´on predefinida repr y,
por tanto, se espera que devuelva una cadena que, de ser evaluada con eval, diera lugar a
un objeto igual al de partida.
c
Universitat Jaume I 2009-2010
Page 30
30II26 Procesadores de lenguaje
Emulaci´on de secuencias y diccionarios
Con los siguientes m´etodos se pueden “simular” los objetos nativos del Python.
__len__(self) debe devolver la longitud del objeto. Se llama al utilizar la funci´on len sobre el
objeto.
__getitem__(self,k) se invoca sobre el objeto x al hacer x[k]. Permite utilizar el objeto como
diccionario.
__setitem__(self,k,v) se invoca sobre el objeto x al hacer x[k]=v. Permite utilizar el objeto
como diccionario.
__delitem__(self,k) se invoca sobre el objeto x al hacer del x[k].
__getslice__(self,i,j) se invoca al hacer x[i:j].
__setslice__(self,i,j,s) se invoca al hacer x[i:j]=s.
__delslice__(self,i,j) se invoca al hacer del x[i:j].
Emulaci´on de tipos num´ericos
Con los siguientes m´etodos se pueden emplear los operadores que normalmente se utilizan con
n´umeros.
__add__(self,r) se invoca con la expresi´on x+r. Existen funciones an´alogas para otros operado-
__radd__(self,l) se invoca con la expresi´on l+x. De manera an´aloga, se pueden definir las ope-
raciones de la lista anterior pero empezando por __r.
__neg__(self) se invoca con -x. Para los operadores unarios +, abs y ~ tenemos __pos__,
__abs__ e __invert__, respectivamente.
10.2.Atributos especiales
Adem´as de los m´etodos especiales, los objetos tienen algunos atributos especiales que nos
permiten cierta “introspecci´on”. Algunos de estos atributos son:
__dict__ es un diccionario que contiene los atributos “normales” de la clase.
__class__ contiene la clase a la que pertenece el objeto. De la clase te puede interesar el atributo
__name__ que contiene el nombre de la clase.
As´ı:
>>> class Clase:
...def __init__(self, v):
...self.v= v
...
>>> a= Clase(3)
>>> a.__dict__
{’v’: 3}
>>> a.__class__.__name__
’Clase’
Page 31
Introducci´on a Python31
10.3.Clases derivadas
Crear clases derivadas en Python es especialmente sencillo. Basta con poner, en la declaraci´on
de la clase derivada, el nombre de la clase base entre par´entesis. La clase derivada puede redefinir
cualquier m´etodo de la clase base. En caso de que alguno de los m´etodos no se redefina, la invocaci´on
del m´etodo en una instancia de la clase derivada provoca una invocaci´on del correspondiente
m´etodo de la clase base:
>>> class Base:
...def __init__(self, v):
...self.v= v
...print "Inicializo la base con un %d" % v
...def f1(self, n):
...return "f1 de la base recibe un %d" % n
...def f2(self, n):
...return "f2 de la base recibe un %d" % n
...
>>> class Derivada(Base):
...def __init__(self, v):
...Base.__init__(self,v)
...print "Se ha inicializado la derivada con %d" % self.v
...def f2(self, n):
...return "f2 de la derivada recibe un %d" % n
...
>>> a= Derivada(4)
Inicializo la base con un 4
Se ha inicializado la derivada con 4
>>> a.f1(2)
’f1 de la base recibe un 2’
>>> a.f2(2)
’f2 de la derivada recibe un 2’
F´ıjate en lo que hemos hecho para llamar al constructor de la clase base, si se define un
constructor para la clase derivada, no se llama al de la clase base. En este caso particular, habr´ıa
bastado con no definir ning´un constructor para la derivada y todo habr´ıa funcionado.
10.4.Ejemplo: una clase para ´arboles de b´usqueda
Vamos a crear una clase que nos permita almacenar ´arboles de b´usqueda. Las clases nos permiten reflejar de manera natural la estructura recursiva del ´arbol. Un objeto de tipo ´arbol tendr´a
tres atributos:
elto: el elemento en la ra´ız del ´arbol.
izdo, dcho: los sub´arboles izquierdo y derecho.
Al constructor le pasaremos el elemento que se almacenar´a en la ra´ız:
class Arbol:
def __init__(self, elto):
self.elto= elto
self.izdo= None
self.dcho= None
c
Universitat Jaume I 2009-2010
Page 32
32II26 Procesadores de lenguaje
Para insertar un elemento, primero comprobamos si coincide con el de la ra´ız. Si no est´a, lo
insertamos en el sub´arbol izquierdo o derecho, seg´un corresponda. Tenemos que tener cuidado para
evitar problemas cuando el sub´arbol donde vamos a hacer la inserci´on no existe.
def inserta(self, nuevo):
if nuevo== self.elto:
return self
elif nuevo< self.elto:
if self.izdo== None:
self.izdo= Arbol(nuevo)
else:
self.izdo= self.izdo.inserta(nuevo)
else:
if self.dcho== None:
self.dcho= Arbol(nuevo)
else:
self.dcho= self.dcho.inserta(nuevo)
return self
Hemos hecho que devuelva el ´arbol para permitir inserciones “en cadena” como
Arbol(3).inserta(2).inserta(4).
Finalmente, comprobar si un elemento est´a en el ´arbol es trivial:
def esta(self, buscado):
if buscado== self.elto:
return True
elif buscado< self.elto:
if self.izdo== None:
return False
else:
return self.izdo.esta(buscado)
else:
if self.dcho== None:
return False
else:
return self.dcho.esta(buscado)
Ejercicio 9
Define el m´etodo __str__ de modo que devuelva una representaci´on apropiada del ´arbol.
Ejercicio 10
Tambi´en podemos implementar los ´arboles guard´andonos un atributo que indique si est´a o no
vac´ıo. El constructor ser´ıa algo as´ı como:
class Arbol:
def __init__(self):
self.vacio= True
La inserci´on crear´ıa el atributo elto y los atributos izdo y dcho.
Implementa esta versi´on de la clase Arbol.
Page 33
Introducci´on a Python33
10.5.Ejemplo: una clase para representar expresiones sencillas
Vamos a definir una clase AST para representar expresiones num´ericas con sumas y multiplicaciones. Necesitar´as una estructura similar a esta para construir el ´arbol de sintaxis abstracta, por
lo que es aconsejable que entiendas perfectamente este programa.
De la clase AST derivamos las dos clases Operacion y Numero que formar´an respectivamente
los nodos y las hojas del ´arbol.
#!/usr/bin/env python
class AST:#------------------------------------------------------------
def __init__(self): pass
def mostrar(self): pass# muestra la expresi´on utilizando par´entesis
def numero_operaciones(self): pass # muestra el n´umero de operaciones de la expresi´on
def interpreta(self): pass# evalua la expresi´on
class Numero(AST):#------------------------------------------------------------
# p.e. para crear una hoja con el d´ıgito 7 har´ıamos Numero(7)
def __init__(self, valor):
self.valor = valor
def mostrar(self):
return str(self.valor)
def numero_operaciones(self):
return 0
def interpreta(self):
return self.valor
class Operacion(AST):#-----------------------------------------------------------
# p.e. para crear un nodo con la expresi´on 5*3 har´ıamos
#Operacion(’*’,Numero(5),Numero(3))
def __init__(self, op, izda, dcha):
# Programa principal ---------------------------------------------------------------
# Introducimos el ´arbol de la expresi´on 4*5 + 3*2
num1=Numero(4)
num2=Numero(5)
num3=Numero(3)
num4=Numero(2)
arbol1=Operacion(’*’,num1,num2) # 4*5
arbol2=Operacion(’*’,num3,num4) # 3*2
arbol_final=Operacion(’+’,arbol1,arbol2) # arbol1+arbol2
# Accedemos al ´arbol de tres formas diferentes mediante funciones miembro
c
Universitat Jaume I 2009-2010
Page 34
34II26 Procesadores de lenguaje
print ’El ´arbol contiene la expresi´on:’, arbol_final.mostrar()
print ’El ´arbol contiene en total %d operaciones’ % arbol_final.numero_operaciones()
print ’La expresi´on se evalua como:’, arbol_final.interpreta()
Al ejecutar el programa anterior, se construye un ´arbol con la expresi´on 4∗ 5+ 3∗ 2 y se obtiene
la siguiente salida:
El ´arbol contiene la expresi´on: ((4*5)+(3*2))
El ´arbol contiene en total 3 operaciones
La expresi´on se evalua como: 26
Ejercicio 11
Ampl´ıa la clase Operacion para que incluya restas y divisiones.
Dif´ıcil (pero no mucho): modifica el m´etodo mostrar para que no escriba par´entesis si no es
necesario seg´un las reglas de prioridad habituales.
10.6.Ejemplo: una clase para representar conjuntos de enteros no negativos
Vamos a definir una clase para representar conjuntos de enteros no negativos. Para ello trabajaremos internamente con un entero largo en el que cada bit indicar´a la presencia o ausencia del
elemento.
#!/usr/bin/env python
from types import *
from math import *
class IntSet:
def __init__(self): # inicializaci´on
self.c = 0L
def __str__(self): # impresi´on del resultado
c = self.c
s = "{ "
i = 0
while c != 0:
j = 2**long(i)
if c & j:
s = s + str(i) + ’ ’
c = c - j
i = i + 1
s = s + "}"
return s
# inserci´on de un entero o
# de una lista de enteros
def insert(self, n):
if type(n) != ListType:
self.c = self.c | 2**long(n)
else:
for i in n:
self.c = self.c | 2**long(i)
def __len__(self):
c = self.c
i = 0
n = 0
while c != 0:
j = 2**long(i)
if c & j:
c = c - j
n = n + 1
i = i + 1
return n
def __getitem__(self, i):
return (self.c & 2**long(i)) != 0
def __setitem__(self, i, v):
s = 2**long(i)
self.c = self.c | s
if v == 0:
self.c = self.c ^ s
def __or__(self, right):# Uni´on
R = IntSet()
R.c = self.c | right.c
return R
def __and__(self, right):# Intersecci´on
R = IntSet()
R.c = self.c & right.c
return R
def __sub__(self, right):# Diferencia
R = IntSet()
R.c = self.c ^ (self.c & right.c)
return R
if __name__ == "__main__":
A = IntSet()
A.insert(10)
A.insert([2, 4, 32])
print "Conjunto A:", A
print "Long:", len(A)
print "¿Est´a el 2?",A[2], "¿Y el 3?", A[3]
A[3] = 1; A[2] = 0
print "¿Est´a el 2?",A[2], "¿Y el 3?", A[3]
print "Conjunto A:", A
B = IntSet()
B.insert([3,7,9,32])
print "B es", B
print "A uni´on B es", A|B
Page 35
Introducci´on a Python35
print "A intersecci´on B es", A&B
print "A \\ B es", A-B
print ((A|B) - (A&B)) - A
11.Un ejercicio adicional
Este ejercicio consistir´a, b´asicamente, en escribir un programa que permita obtener informaci´on
sobre los usuarios de un sistema Unix a partir del contenido del fichero /etc/paswd. En realidad,
lo que se pretende es escribir versiones cada vez m´as refinadas del programa siguiente:
sys.stdout.write("¿Usuario?: ")
linea=sys.stdin.readline()
if not linea:
break
login=string.strip(linea)
if usuarios.has_key(login):
print ""+usuarios[login]
else:
print "Usuario desconocido"
print
print "¡Hasta otra!"
Una vez hayas entendido perfectamente c´omo funciona el programa anterior, ve introduci´endole
las siguientes modificaciones:
1. Haz que tu programa muestre m´as informaci´on sobre el usuario, no s´olo el quinto campo de la
correspondiente l´ınea del fichero de contrase˜nas (esto es, nombre del usuario y comentarios).
Ten en cuenta, por ejemplo, que el tercer campo corresponde al uid y el cuarto, al gid.
Define una clase DatosUsuario cuyos diferentes atributos correspondan a diferentes datos
del usuario, de forma que el diccionario usuarios relacione el login de cada usuario con un
objeto de la clase. Dota a la clase de un m´etodo de inicializaci´on que permita asignar valores
a los diferentes atributos del objeto en el momento de su creaci´on. Considera la posibilidad
de dotar tambi´en a la clase de un m´etodo __str__().
2. Haz que la informaci´on que se muestre de cada usuario incluya tambi´en el n´umero de usuarios
en su grupo y una relaci´on de los mismos. Puedes hacer que no se imprima el login de todos
y cada uno de los miembros del grupo, sino s´olo el de los diez primeros en orden alfab´etico.
Parece razonable almacenar la informaci´on de los diferentes grupos en un diccionario grupos
que se vaya construyendo al mismo tiempo que usuarios.
c
Universitat Jaume I 2009-2010
Page 36
36II26 Procesadores de lenguaje
3. Haz que, al pedirle la informaci´on de un usuario, el programa muestre el nombre del grupo,
en vez de su gid, si este dato est´a presente en /etc/group. En este fichero, en el que los
diferentes campos tambi´en est´an separados por el car´acter dos puntos, el primero corresponde
al nombre del grupo y el tercero, a su gid. Haz que se procese el fichero en una sola pasada
para actualizar con ´el la informaci´on recogida en el diccionario grupos.
4. Haz que exista la posibilidad de especificar en la l´ınea de ´ordenes, al llamar al programa,
unos ficheros de contrase˜nas y de grupos diferentes de los habituales. Suponiendo que el
programa se llame infouser, la orden deber´a tener el siguiente perfil:
usage: infouser [fich_usuarios [fich_grupos]]
5. Introduce diferentes controles de error en el programa. Define una funci´on error() que reciba
como argumento una cadena que describe el error, la muestre por la salida de error est´andar
y finalice la ejecuci´on del programa devolviendo al int´erprete de ´ordenes (shell ) un status 1.
Los diferentes errores que puedes controlar son: un n´umero inadecuado de argumentos en la
l´ınea de ´ordenes, problemas en la apertura de los ficheros y que sus l´ıneas no sigan el formato
esperado. Los dos ´ultimos tipos de errores puedes intentar capturarlos con construcciones
try-except. Trata los errores de apertura de ficheros de forma que, si estos afectan a ambos
ficheros, se informe al usuario de ello antes de abortar la ejecuci´on.
6. Haz que el uid tambi´en sea una forma v´alida de solicitar al programa la informaci´on de un
usuario. Utiliza re.match() para discriminar si lo le´ıdo puede ser un uid (esto es, si es una
secuencia de d´ıgitos) o no, en cuyo caso ser´a un posible login. Considera la utilidad de haber
construido un tercer diccionario para relacionar cada uid con su correspondiente login.
7. Considera la posibilidad de mejorar el formato de la salida de tu programa utilizando las
herramientas descritas al comienzo del cap´ıtulo 7 del Python Tutorial.
A.Soluciones a algunos ejercicios
A.1.Sobre tipos de datos
Ejercicio 1:
Veamos dos posibilidades distintas, seg´un qu´e delimitador se utilice para la cadena:
>>> print "’\\/\""
’\/"
>>> print ’\’\\/"’
’\/"
Ejercicio 2:
Una posible soluci´on ser´ıa esta:
>>> a=’esto es un ejemplo’
>>> print a[8:]+a[4:8]+a[:4]
un ejemplo es esto
Ejercicio 3:
La modificaci´on de a podr´ıa llevarse a cabo como sigue:
La asignaci´on de la lista [3] a la variable b no modifica el objeto al que anteriormente hac´ıa
referencia esa variable (la lista [1,2]), que sigue tal cual, ligado ahora tan s´olo a las referencias
c[0] y c[1]. Esto es a diferencia de lo que suced´ıa en el primer caso, ya que la asignaci´on b[0]=2
s´ı modificaba un objeto: el ligado a las referencias b, c[0] y c[1], que pasaba de ser la lista [1,2]
a ser la lista [2,2].
Volviendo al segundo caso, obs´ervese que las referencias c[0] y c[1] lo son al mismo objeto,
de modo que la secuencia de ´ordenes al int´erprete de Python podr´ıa haber seguido as´ı:
Utilizando un bucle while, el programa podr´ıa ser el siguiente:
#!/usr/bin/env python
lista=[]
i=1
while i<=10:
lista.append(i)
i=i+1
print lista
Con un bucle for, la soluci´on podr´ıa ser esta:
#!/usr/bin/env python
lista=[]
for i in range(10):
lista.append(i+1)
print lista
Obs´ervese que el siguiente programa, que no utiliza bucle alguno, es equivalente:
#!/usr/bin/env python
lista=range(1,11)
print lista
Ejercicio 6:
Lo que se pide es, en realidad, un fragmento de programa. Supongamos que el nombre de la
tupla dada es precisamente tupla. La construcci´on de la lista (que llamaremos lista) podr´ıa
realizarse como sigue:
lista=[]
for elemento in tupla:
lista.append(elemento)
Lo anterior es correcto porque for permite iterar sobre los elementos de cualquier secuencia
(no s´olo sobre listas, sino tambi´en sobre tuplas e incluso cadenas). De no haberlo tenido en cuenta,
la siguiente hubiera sido una alternativa razonable:
c
Universitat Jaume I 2009-2010
Page 38
38II26 Procesadores de lenguaje
lista=[]
for i in range(len(tupla)):
lista.append(tupla[i])
Por ´ultimo, podemos utilizar list para hacer lo mismo:
lista= list(tupla)
Ejercicio 7:
El ejercicio pide un programa como el siguiente:
#!/usr/bin/env python
for i in range(1,1001):
if i%7==0:
print i
Obviamente, el if podr´ıa evitarse recorriendo la lista de m´ultiplos de 7 que genera range(7,1001,7),
o bien recorriendo range(1,1000/7+1) e imprimiendo 7*i.
A.3.Sobre funciones
Ejercicio 8:
El ejercicio pide un programa como el siguiente:
#!/usr/bin/env python
def multiplo7(n):
if n%7==0:
return True
else:
return False
for i in range(1,1001):
if multiplo7(i)==1:
print i
Adem´as, sabiendo que en Python las operaciones de comparaci´on devuelven un resultado False
para representar el valor l´ogico falso y un resultado True para el valor verdadero, la funci´on podr´ıa
reescribirse simplemente como sigue:
def multiplo7(n):
return n%7==0
Tambi´en sucede que las condiciones de las construcciones if y while no es necesario que
sean comparaciones, sino que pueden ser objetos cualesquiera: el lenguaje les asocia un valor
l´ogico concreto siguiendo las reglas que vimos en la secci´on 3.1, lo que nos permitir´ıa sustituir la
comparaci´on multiplo7(i)==True por, simplemente, multiplo7(i).
B.Preguntas frecuentes
1: Escribo un programa Python en un fichero, escribo el nombre del fichero en el int´erprete
de ´ordenes (shell) y el programa no se ejecuta. ¿Por qu´e?
Hay tres errores que se cometen con cierta frecuencia y que conviene evitar. Comprueba lo
siguiente:
El fichero tiene una primera l´ınea que indica correctamente a la shell que es Python quien
ha de ejecutar el programa. Una l´ınea como
#!/usr/bin/env python
Page 39
Introducci´on a Python39
deber´ıa servir en cualquier instalaci´on razonable de Unix.
El fichero tiene los permisos de ejecuci´on adecuados (si no es as´ı, utiliza chmod).
El directorio donde se encuentra el fichero est´a en tu PATH. Puedes utilizar echo $PATH
para comprobarlo. Si, por ejemplo, necesitas modificar el PATH para que incluya al directorio
actual, haz lo siguiente:
export PATH=.:$PATH
Si te preocupa el problema de seguridad que representa poner . en el PATH, puedes ejecutar
el programa a˜nadiendo ./ delante del nombre.
2: ¿Por qu´e Python da un error cuando intento a˜nadir un elemento a una lista y ordenar la
lista resultante con lista.append(elemento).sort()?
Simplemente, porque append() no devuelve como resultado la lista con el elemento a˜nadido,
sino que s´olo modifica la propia lista a˜nadi´endole un nuevo elemento. Lo mismo sucede con sort(),
que no devuelve como resultado la lista ordenada, sino que ordena la propia lista. Es importante
que distingas lo que una operaci´on devuelve como resultado y los efectos secundarios (side effects)
de la operaci´on. As´ı, tras a=[3,5],
b=a.append(4) har´ıa que el valor de a fuera [3,5,4] y el de b fuera None, mientras que
b=a+[4] no modificar´ıa el valor de a (seguir´ıa siendo [3,5]), pero el de b ser´ıa [3,5,4].
Esto ´ultimo es as´ı porque lista+[elemento] s´ı devuelve como resultado una nueva lista, pero no
tiene efectos secundarios sobre la lista original.
Volviendo a la pregunta original, el error se produce porque lista.append(elemento), al no
devolver resultado alguno, lo que hace es devolver un objeto None, sobre el cual es incorrecto
intentar aplicar un m´etodo sort().
3: En Python, ¿existe alguna diferencia entre las cadenas delimitadas por comillas simples y
las delimitadas por comillas dobles?
En principio, tanto las comillas simples como las dobles son dos m´etodos alternativos para
delimitar literales de cadena (esto es, aquellos lexemas que nos permiten representar en un lenguaje
de programaci´on, Python en el caso que nos ocupa, el valor de una cadena). As´ı, por ejemplo,
’hola’ y "hola" son notaciones alternativas y equivalentes para la cadena formada por los cuatro
caracteres siguientes: hache, o, ele y a.
Cualquier cadena puede representarse en Python utilizando como delimitadores comillas simples, y lo mismo puede decirse de las dobles. No obstante, existe una peque˜na diferencia entre
unas y otras. Sabemos que a veces, para representar la presencia de un car´acter en una cadena, es
necesario utilizar en el literal de cadena m´as de un car´acter (lo que se conoce como una secuenciade escape). As´ı, el salto de l´ınea se representa mediante una barra invertida y el car´acter ene
(\n), la comilla simple se representa como \’ y para la doble se utiliza \". Ahora bien, cuando se
utilizan comillas simples como delimitadores, las dobles pueden representarse a s´ı mismas en los
literales de cadena, y viceversa, de modo que los cuatro literales siguientes representan todos ellos
a la cadena formada por una comilla simple y otra doble:
’\’\"’
’\’"’
"\’\""
"’\""
c
Universitat Jaume I 2009-2010
Page 40
40II26 Procesadores de lenguaje
4:Escribo un programa Python en el que se comparan dos cadenas, una le´ıda mediante
readline() y la otra representada mediante un literal, y el programa siempre las considera
distintas (aunque aparentemente sean iguales). ¿Por qu´e?
Las cadenas que devuelve readline() son l´ıneas enteras, incluyendo el car´acter de salto de
l´ınea (salvo que este no est´e presente en el fichero le´ıdo por haberse alcanzado antes el fin del
fichero). As´ı, si por ejemplo el programa est´a leyendo una respuesta de la entrada est´andar con
resp=sys.stdin.readline(), el usuario teclea ene, o y enter y el programa eval´ua la comparaci´on
resp==’no’, el resultado ser´a de falsedad (0), porque la cadena resp tendr´a, adem´as de la ene
y la o de ’no’, un tercer car´acter: el de salto de l´ınea. En una primera aproximaci´on, se podr´ıa
solucionar este problema siguiendo una cualquiera de las dos estrategias siguientes:
Escribir la comparaci´on como resp==’no\n’, incluyendo el car´acter de salto de l´ınea tambi´en
en la cadena representada mediante literal.
Eliminar el salto de l´ınea de la cadena le´ıda, por ejemplo con resp=resp[:-1].
Las soluciones anteriores, aparte de no ser muy elegantes, pueden dar lugar a resultados indeseados si el usuario, tras la ene y la o, introduce inmediatamente el fin del fichero. Una soluci´on
m´as general, que no adolece de estos problemas, ser´ıa utilizar rstrip() como se ejemplifica a
continuaci´on:
resp=resp.rstrip()
De este modo, se eliminar´ıan de la cadena le´ıda tanto un eventual car´acter final de salto de
l´ınea como todos los posibles blancos iniciales y finales que el usuario hubiera podido introducir
inadvertidamente.
5: Muy bien, pero ¿c´omo puede una l´ınea devuelta por readline no tener fin de l´ınea?
Si el fichero se termina antes de que aparezca un fin de l´ınea, la ´ultima l´ınea le´ıda no tendr´a
fin de l´ınea. Si la pregunta es ¿c´omo puede un fichero no tener un fin de l´ınea en cada l´ınea?,
hay varias posibilidades. Puedes crear f´acilmente con emacs un fichero as´ı (vi no sirve para esto;
siempre a˜nade finales de l´ınea). Otra posibilidad es hacer algo parecido a lo siguiente:
6:En Python, ¿c´omo puedo saber si una cadena pertenece al lenguaje definido por una
expresi´on regular?
Para trabajar con expresiones regulares, Python ofrece el m´odulo re, con dos funciones,
match() y search(), ´utiles para nuestros prop´ositos. No obstante, hay que tener en cuenta lo
siguiente:
re.match(er,c) comprueba si alg´un prefijo de la cadena c casa con la expresi´on regular
er (an´alogamente sucede con erc.match(c) si erc es una expresi´on regular compilada con
erc=re.compile(er)).
re.search(er,c) (o bien erc.search(c) si erc es una versi´on compilada de er) compruebasi alguna subcadena de c casa con er.
Page 41
Introducci´on a Python41
Para saber si precisamente la cadena c (no alguno de sus prefijos o de sus subcadenas) casa con
er, lo que puede hacerse es incorporar en la expresi´on regular los puntos de anclaje inicial (^)
y final ($), que s´olo casan con el inicio y el fin de la cadena, respectivamente (y luego utilizar
indistintamente match() o search()). Por ejemplo, lo siguiente deber´ıa funcionar:
if re.match(’^’+er+’$’,c): print ’OK’
7: En Python, ¿qu´e diferencia hay entre las asignaciones a[2] = [6,7] y a[2:3] = [6,7]?
En el primer caso se sustituye el elemento en la posici´on dos por la lista asignada. La lista
contin´ua teniendo cuatro elementos pero ahora uno de ellos es una lista:
En el segundo caso se sustituye el elemento en la posici´on dos por los elementos de la lista
asignada. Para este ejemplo concreto, la lista pasa a tener un elemento m´as: