Вы находитесь на странице: 1из 19

Apéndice A

Python

En este apéndice resumimos aquellos aspectos del lenguaje de programación Python (versión 2.4) de los
que hacemos uso, prestando especial atención a las caracterı́sticas que no encontramos en otros lenguajes
imperativos u orientados a objetos. Este apéndice no es un tutorial y sólo entra en detalle al considerar
cuestiones que diferencian a Python de otros lenguajes convencionales como C o C++. Para aprender el
lenguaje de programación se recomienda el tutorial de Guido van Rossum que se incluye en la distribución
del intérprete.

A.1. Formato
Los programas Python se escriben en ficheros de texto con formato y se organizan en lı́neas lógicas. Éstas
sueles corresponderse con lı́neas fı́sicas, aunque no siempre es ası́. En ciertos caso, por ejemplo, el punto y
coma permite unir dos lı́neas lógicas en una lı́nea fı́sica y la barra invertida permite dos lı́neas fı́sicas para
formar una lı́nea lógica. Si un paréntesis está abierto y finaliza una lı́nea fı́sica, se entiende que la lı́nea
lógica continúa hasta el cierre del paréntesis.
Hay sentencias simples y compuestas. Las sentencias simples (expresiones, salida por pantalla, etc.)
son parte de una sola lı́nea lógica. Las estructuras de control y las definiciones de funciones y clases son
sentencias compuestas, y se componen de una o más cláusulas. Una cláusula es una cabecera y una suite.
Las cláusulas presentan el mismo nivel de indentación y las suites presentan mayor indentación que sus
respectivas cabeceras. Cada cabecera empieza con una palabra clave y finaliza con dos puntos. Python no
es, pues, un lenguaje de formato libre. Una suite no puede estar vacı́a. Si se desea que no contenga acción
alguna puede usarse la sentencia pass.
Todos los caracteres desde la almohadilla (((#))) hasta el fin de lı́nea fı́sica constituyen un comentario y
son ignorados.
Un fichero de texto que sólo contiene definiciones de funciones, clases y variables (y quizá código de
inicialización) es un módulo. Un programa puede hacer uso de funciones, clases y variables definidas en
un módulo.

A.2. Salida por pantalla


La palabra reservada print puede ir seguida de una o más expresiones (separadas por comas) y muestra en
pantalla el resultado de evaluarlas (separadas por espacios).
1 print 1
2 print 2, 3

1
2 3

Si una sentencia print finaliza en una coma, no se añade un salto de lı́nea:


1 print 1,
2 print 2, 3

1 2 3

Una sentencia print sin expresiones imprime un salto de lı́nea.

Apuntes de Algorı́tmica A-1


A.3 Variables 2004/09/24-15:53

A.3. Variables
Python es un lenguaje tipado dinámicamente: las variables no tienen tipo, pero sı́ los valores que se asignan
a variables y/o que participan en expresiones. Se puede asignar un valor a una variable con el operador ((=)).
En este ejemplo se asigna el valor 2 a la variable 2 y se muestra por pantalla el valor asignado:

1 a=2
2 print a

Debe tenerse en cuenta que una variable no ((contiene)) el valor que se le asigna, sino que mantiene una
referencia al lugar de memoria en el que éste reside. La gestión de memoria dinámica es tarea del intérprete
y no es necesario liberar explı́citamente la memoria reservada: Python usa conteo de referencias y técnicas
de detección de ciclos para liberar la memoria no utilizada.

A.4. Tipos básicos


A.4.1. Escalares
Python permite trabajar directamente con datos de tipo lógico (o booleano), enteros, números en coma
flotante y números complejos.

Lógicos
Los valores lógicos son True (((cierto))) y False (((False))), si bien muchos valores especiales de otros tipos
pueden jugar el papel de ((cierto)) o ((falso)): el entero 0 es falso y cualquier otro entero es cierto, una
colección vacı́a es falso y cualquier otra es cierto, etc.

Enteros
Los literales de enteros siguen las reglas léxicas de C y pueden codificarse en decimal, octal y hexadecimal.
Los enteros pueden formarse con un número arbitrariamente grande de dı́gitos.
Versiones anteriores de Python distinguı́an entre enteros y ((enteros largos)) (enteros con un número
arbitrariamente grande cifras), que hoy son tipos unificados. No obstante, al mostrar en pantalla un entero
largo aparece el carácter L al final del mismo. Este sufijo explicita que se trata de un entero largo.

En coma flotante
Los números en coma flotante son asimilables a los datos de tipo double en C y sus literales se expresan
del mismo modo que en dicho lenguaje. El resultado de operar un entero con un valor en coma flotante
proporciona un valor en coma flotante.

Complejos
Un número complejo puro se representa con un número entero o en coma flotante finalizado con la letra j.
Un complejo con parte real e imaginaria se obtiene, por ejemplo, sumando un número en coma flotante a
un número imaginario.

1 print (2 + 2j)/(2 - 4j)

(-0.2+0.6j)

None
None es un valor especial que se usa para indicar la ausencia de valor o para señalar una situación excep-
cional.

A-2 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

A.4.2. Colecciones
Un colección es un multiconjunto de datos. Una secuencia es un multiconjunto ordenado de datos, cada
uno de los cuales es accesible mediante un ı́ndice. Un mapeo es una correspondencia entre claves y valores.
Un conjunto propiamente dicho es una colección sin repeticiones (ni orden alguno). Python ofrece soporte
directo para secuencias (listas y tuplas), mapeos (diccionarios) y conjuntos propiamente dichos. Ofrece
implementaciones de otros tipos estructurados (deques y heaps, por ejemplo) a través de bibliotecas.

Listas
Las listas Python equivalen a vectores dinámicos (con información de longitud) en lenguajes de progra-
mación como C, o al tipo vector de la STL en C++. Podemos expresar literales encerrando sus elementos
entre un par de corchetes y separándolos con comas:
1 an array = [1, 2, 3, 5, 7, 11]
2 empty array = []
El primer elemento de una lista tiene ı́ndice 0. El operador de indexación accede a un elemento y se expresa
sintácticamente añadiendo a la lista su ı́ndice entre corchetes, lista[ı́ndice]:
1 an array = [1, 2, 3, 5, 7, 11]
2 print ’Los dos primeros elementos:’, an array[0], an array[1]

Los dos primeros elementos: 1 2

Es posible utilizar ı́ndices negativos, en cuyo caso se empieza a contar desde el final: −1 es el último
elemento, −2 el penúltimo, etc:
1 an array = [1, 2, 3, 5, 7, 11]
2 print ’Últimos dos elementos:’, an array[-2], an array[-1]

Últimos dos elementos: 7 11

El posible concatenar listas con el operador suma:


1 an array = [1, 2, 3, 5, 7, 11]
2 another array = [13, 17]
3 result = an array + another array

4 print result

[1, 2, 3, 5, 7, 11, 13, 17]

O extender una lista con el método extend:


1 an array = [1, 2, 3, 5, 7, 11]
2 another array = [13, 17]
3 an array.extend(another array)

4 print an array

[1, 2, 3, 5, 7, 11, 13, 17]

Nótese que el método modifica la lista sobre la que se invoca.


El método append extiende una lista elemento a elemento:
1 an array = [1, 2, 3, 5, 7, 11]
2 an array.append(13)
3 an array.append(17)

4 print an array

[1, 2, 3, 5, 7, 11, 13, 17]

El redimensionamiento puede resultar relativamente costoso en tiempo de ejecución, pues en ocasiones


comporta la reserva de nueva memoria y la liberación de la usada hasta el momento. Cuando se conoce el
tamaño máximo de la lista puede resultar conveniente efectuar una reserva previa de toda la memoria que
ha de ocupar. Podemos hacerlo con el operador de repetición, que se representa con un asterisco:

Apuntes de Algorı́tmica A-3


A.4 Tipos básicos 2004/09/24-15:53

1 an array = [0] * 10
2 an array[5] = 3
3 print an array

[0, 0, 0, 0, 0, 3, 0, 0, 0, 0]

La función range devuelve una lista formada con elementos en un rango determinado. La forma general
de range usa tres argumentos: el valor inicial, el lı́mite superior (que se excluye) y el incremento entre
elementos consecutivos. He aquı́ un ejemplo de uso:
1 an array = range(1, 100, 15)
2 print an array

[1, 16, 31, 46, 61, 76, 91]

Si se invoca a range con dos argumentos, el incremento toma el valor uno. Si se invoca con un sólo
argumento, el valor inicial es 0.
1 print range(6), range(1,6), range(1,6,2)

[0, 1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [1, 3, 5]

Comprensión de lista: Una forma elegante de construir listas en Python es mediante la denominada comprensión de listas,
List comprehension. que imita la notación matemática de descripción de conjuntos como ésta:

A = {i2 | 0 ≤ i < 10}.


1 A = [ i**2 for i in range(10) ]
2 print A

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Se pueden utilizar condiciones complejas a la hora de decir qué elementos forman parte de una lista:

A = {i2 | i es par, 0 ≤ i < 10}.


1 print [ i**2 for i in range(10) if i % 2 == 0]

[0, 4, 16, 36, 64]

El operador de corte permite seleccionar una serie de elementos contiguos o equiespaciados en la lista.
El rango de ı́ndices de los elementos seleccionados se indica entre corchetes y separados por dos puntos:
1 an array = range(0, 20, 2)
2 print an array
3 print an array[2:6], an array[2:8:2]

4 print an array[1:-1]

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]


[4, 6, 8, 10] [4, 8, 12]
[2, 4, 6, 8, 10, 12, 14, 16]

Nótese que el elemento cuyo ı́ndice coincide con el segundo elemento del corte no se selecciona.
Algunos elementos del corte pueden omitirse y tomar valor por defecto. El primero ı́ndice vale 0 si no
se explicita y la omisión del segundo hace que sea igual a la longitud de la lista:
1 an array = range(0, 10)
2 print an array[:6], an array[6:], an array[:]

[0, 1, 2, 3, 4, 5] [6, 7, 8, 9] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

En la tabla 3.1 se recogen algunos operadores y métodos de uso común en Python (acompañados de sus
respectivos costes temporales).

A-4 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

Tuplas
Python ofrece, además, la posibilidad de trabajar con tuplas, que son listas inmutables. Sintácticamente,
los literales de tupla se expresan como los de las listas, pero con paréntesis en lugar de corchetes. Sólo hay
un problema: la tupla de un solo elemento se puede confundir con una expresión entre paréntesis, ası́ que
requiere añadir una coma tras su único elemento para romper la ambigüedad.

1 a tuple = (1, 2, 3, 5, 7, 11)


2 empty tuple = ()
3 unitary tuple = (1,)

Una última observación: salvo para la tupla vacı́a, los paréntesis son opcionales:

1 a tuple = 1, 2, 3, 5, 7, 11
2 empty tuple = ()
3 unitary tuple = 1,

Podemos usar los operadores (indexación, corte, etc.) y métodos de las listas que no modifican su
contenido. Podemos, por ejemplo, concatenar dos tuplas (se genera una nueva tupla resultante de unir
ambas), pero no podemos usar el método extend (modificarı́a el contenido de la tupla, que es inmutable).
Podemos obtener una tupla a partir de una lista con la función tuple:

1 print tuple([1,5,3])

(1, 5, 3)

Se pueden efectuar asignaciones múltiples o intercambios del valor de dos variables mediante expre-
siones idiomáticas de Python que hacen uso de tuplas:

1 a, b = 1, 2
2 a, b = b, a
3 print a, b

2 1

Cadenas
Las cadenas Python pueden encerrarse entre comillas simples o dobles. En principio, sigue las reglas de C
para expresar caracteres especiales, es decir, usa la barra invertida para expresar caracteres especiales:

1 print ’una\ncadena’
2 a = "otra\ncadena"
3 print a

una
cadena
otra
cadena

Una cadena que se abre con triples comillas (simples o dobles) puede ocupar varias lı́neas:

1 print ’’’una
2 cadena
3 que ocupa

4 varias lı́neas’’’

una
cadena
que ocupa
varias lı́neas

Apuntes de Algorı́tmica A-5


A.4 Tipos básicos 2004/09/24-15:53

No hay un tipo de datos ((carácter)): un carácter es una cadena de longitud unitaria. Podemos acceder a
un carácter con el operador de indexación y a una subcadena de cualquier longitud con el operador de corte.
Las cadenas son inmutables. Si se desea ((modificar)) el contenido de una cadena se debe generar otra a
partir de la primera.
Es posible concatenar cadenas con el operador ((+)) y repetir una cadena con el operador ((*)). El op-
erador de formato, (( %)), genera una cadena a partir de otra (operando izquierdo) sustituyendo las denom-
inadas ((marcas de formato)) por uno o más valores (operando derecho). Las marcas de formato (y sus
modificadores) se ((inspiran)) en las que encontramos en funciones de C como printf .

1 a=3
2 print ’Valor: %d’ % a

Valor: 3

Si hay más de una marca de formato, los valores deben proporcionarse con una tupla:

1 a = 3.2
2 print ’Dos valores: %f y %d’ % (a, 4)

Dos valores: 3.200000 y 4

Si deseamos obtener una lista de palabras podemos usar el método split:

1 print ’una frase corta’.split()

[’una’, ’frase’, ’corta’]

El método split permite especificar un separador:

1 print ’una:frase::corta’.split(’:’)

[’una’, ’frase’, ’’, ’corta’]

El método strip elimina los blancos iniciales y finales de una cadena, y rstrip, sólo los finales.

1 print ’|’, ’ una cadena ’.strip(), ’|’

| una cadena |

Diccionarios

Los diccionarios permiten asociar valores con claves. Una clave es cualquier objeto inmutable (lo son los
escalares, las tuplas y las cadenas, pero no las listas). Se puede acceder al valor asociado a una clave con el
operador de indexación. En Python, los diccionarios se implementan mediante tablas de dispersión.
Los literales de diccionario son una sucesión de pares (tuplas) clave-valor separados por comas y encer-
rados entre llaves. Los componentes de cada par clave-valor se separan entre sı́ con dos puntos:

1 a dict = {’a’: 1, ’b’: 2, ’c’: 3}


2 empty dict = {}
3 print ’Contenido asociado a "a":’, a dict[’a’]

Contenido asociado a "a": 1

En la tabla 3.3 se recogen algunos operadores y métodos de uso común con diccionarios (acompañados
de sus respectivos costes temporales).

A-6 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

Conjuntos
Python ofrece una implementación de conjuntos basada en tablas de dispersión. La función set construye
un conjunto a partir de una secuencia:
1 a = set([1, 3, 4])
2 print a

set([1, 3, 4])

Los conjuntos soportan operaciones de unión, intersección, pertenencia, etc.


1 a = set([1, 3, 4])
2 b = set([2, 3, 5])
3 print a.union(b), a.intersection(b), 3 in a

set([1, 2, 3, 4, 5]) set([3]) True

En la tabla 3.4 se muestran algunos operadores y métodos para conjuntos.

A.4.3. Coerción
Hay reglas de promoción automática de tipos que permiten operar entre, por ejemplo, un entero y un
flotante. El resultado es siempre del tipo más general.
Es posible convertir datos de un tipo en otro mediante ciertas funciones predefinidas. Éstas suelen
presentar como identificador el nombre del tipo o una abreviatura suya: int para enteros, float para número
en coma flotante, complex para números complejos, list para listas, tuple para tuplas, str para cadenas y dict
para diccionarios.
La función int obtiene la parte entera de un número en coma flotante:
1 print int(2.1), int(2.5), int(2.9)
2 print int(-2.1), int(-2.5), int(-2.9)

2 2 2
-2 -2 -2

La misma función puede aplicarse para interpretar como valor entero un número codificado en una
cadena:
1 print int(’2’+’1’)+1

22

La función float proporciona un número en coma flotante equivalente al entero o cadena (si ésta codifica
un valor numérico) que se le suministra como parámetro.
La función list puede construir una lista con los elementos de una secuencia (una tupla, una cadena,
etc.). La función tuple puede construir una tupla con los elementos de una secuencia.
Se puede transformar una cadena en una lista de caracteres (cadenas de longitud uno) con la función
list:
1 print list( (1, 2, 3) )
2 print list(’cadena’)
3 print tuple([1,2,3])

4 print tuple(’cadena’)

[1, 2, 3]
[’c’, ’a’, ’d’, ’e’, ’n’, ’a’]
(1, 2, 3)
(’c’, ’a’, ’d’, ’e’, ’n’, ’a’)

La función str permite obtener una cadena a partir de cualquier tipo básico:

Apuntes de Algorı́tmica A-7


A.5 Expresiones 2004/09/24-15:53

1 print (str(2) + str(3.1)) * 2


2 print str([1,2])

23.123.1
[1, 2]

Se puede inicializar un diccionario con la función dict y una secuencia de pares clave-valor:
1 print dict([(’a’,1), (’b’, 2), (’c’, 3)])
2 print dict([(i, i**2) for i in range(10) if i % 2 == 0])

{’a’: 1, ’c’: 3, ’b’: 2}


{0: 0, 8: 64, 2: 4, 4: 16, 6: 36}

A.5. Expresiones
Al operar con escalares, los operadores Python son los mismos que encontramos en el lenguaje C y siguen
sus reglas de precedencia y asociatividad, con algunas excepciones:
Los operadores lógicos se denotan con las palabras reservadas and, or y not.
Los operadores de comparación no siguen las reglas de precedencia convencionales en otros lengua-
jes. Una expresión como a < b <= c > d equivale a a < b and b <= c and c > d.
No hay operador de pre o postincremento ni operador de pre o postdecremento.
Se puede efectuar asignaciones con operador para simplicar operaciones de incremento (((+=))), decre-
mento (((-=))), etc.:
1 a=2
2 print a,
3 a += 2

4 print a

2 4

Python ofrece operadores que no tienen correlato en C o C++:


Operador de exponenciación, que se denota con ((**)) y que es asociativo por la derecha.
Operador de pertenencia. Se denota con la palabra clave in. Devuelve ((cierto)) si el operando izquier-
do está incluido al operando derecho (normalmente, un contenedor). El operador not in devuelve
((cierto)) cuando in devuelve ((falso)) y viceversa.

A.6. Estructuras de control


Las estructuras de control permiten ejecutar bloques de código condicionalmente o iterar su ejecución
mientras se observe cierta condición.

A.6.1. De selección
Para supeditar la ejecución de un bloque a la satisfacción de una condición se usa la sentencia if:
1 a = 102
2 if a % 2 == 0:
3 print ’ %d es par’ % a

102 es par

La sentencia if puede extenderse con varios elif (abreaviatura de ((else if ))), cado uno con su propia
condición, y opcionalmente un else final. Sólo se ejecuta uno de los bloques: el de la primera condición
que se cumple o, si no se cumple ninguna, el asociado al else (si lo hay).

A-8 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

1 a = 45
2 if a % 2 == 0:
3 print ’ %d es par’ % a
4 elif a % 3 == 0:

5 print ’ %d no es par y es divisible por 3’ % a


6 else:

7 print ’ %d no es par ni divisible por 3’ % a

45 no es par y es divisible por 3

A.6.2. De repetición (o bucle)


La sentencia while permite iterar la ejecución de un bloque mientras se cumpla una condición:

1 a = 10
2 while a > 0:
3 print a,
4 a -= 1

10 9 8 7 6 5 4 3 2 1

La sentencia for-in permite recorrer una secuencia de valores. Una variable ı́ndice toma, ordenada-
mente, un valor de la secuencia con cada iteración:

1 for indice in 1, "dos", 3:


2 print indice,
3 print

5 for i in range(2, 6):


6 print i,
7 print

1 dos 3
2 3 4 5

Si se desea recorrer los elementos en orden inverso se puede recurrir a la función reversed:

1 for i in reversed(range(2, 6)):


2 print i,
3 print

5 4 3 2

La sentencia break interrumpe la ejecución de un bucle (while o for-in) y la sentencia continue hace
pasar inmediatamente a la siguiente iteración, sin ejecutar el resto del bloque. Tanto break como continue
afectan únicamente al bucle que las contiene directamente.

A.6.3. Excepciones
Al cargar un programa o módulo, el intérprete efectúa comprobaciones léxicas y sintácticas. Sólo aquellos
que superan esta etapa pasan a ser interpretados. En ejecución pueden producirse errores semánticos: op-
eradores aplicados sobre operandos de tipos no compatibles con la operación, divisiones por cero, intentos
de acceso fuera de rango a elementos de una lista, etc. Cuando se produce un error en tiempo de ejecución,
el intérprete de Python lanza una excepción y, si no es tratada, aborta la ejecución del programa.

1 a = 1/0
2 print ’Fin’

Apuntes de Algorı́tmica A-9


A.6 Estructuras de control 2004/09/24-15:53

E Traceback (most recent call last):


File "test_sel.py", line 1, in ?
a = 1/0
ZeroDivisionError: integer division or modulo by zero

Las excepciones pueden tratarse con la estructura try-except:

1 try:
2 a = 1/0
3 except:

4 print ’Excepción en el bloque entre try y except.’


5 print ’Fin’

Excepción en el bloque entre try y except.


Fin

Una excepción es una instancia de cierta clase que hereda de la clase Exception. Hay toda una jerarquı́a
de excepciones, lo que permite que podamos capturar y tratar por separado cada tipo de error detectado:

1 a=1
2 array = []
3 try:

4 if a == 0:
5 print 1/0
6 else:
7 print array[10000]
8 except ZeroDivisionError:

9 print ’División por cero en el bloque entre try y except:’


10 except IndexError:

11 print ’Error de indexación en el bloque entre try y except:’

Error de indexación en el bloque entre try y except:

Las excepciones pueden venir acompañadas de un mensaje que detalla el error:

1 a=1
2 array = []
3 try:

4 if a == 0:
5 print 1/0
6 else:
7 print array[10000]
8 except ZeroDivisionError, msg:

9 print ’División por cero en el bloque entre try y except’, msg


10 except IndexError, msg:

11 print ’Error de indexación en el bloque entre try y except’, msg

Error de indexación en el bloque entre try y except list index out of range

Si el código donde se produce un error es parte de una función que está siendo invocada desde el
programa principal o desde otra función, su ejecución se interrumpe a menos que la lı́nea causante de la
excepción esté en un bloque try-except capaz de capturar esa excepción. Ocurre lo mismo con la función,
si la hay, desde la que se produjo la llamada. Las tramas de activación van desapilándose hasta que una
función o el programa principal atrapen la excepción. Si nadie lo hace, el intérprete la captura e interrumpe
la ejecución del programa.
Podemos generar nuestras propias excepciones con la sentencia raise:

1 raise IndexError

A-10 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

E Traceback (most recent call last):


File "test_sel.py", line 1, in ?
raise IndexError
IndexError

1 raise IndexError, ’Texto explicativo.’

E Traceback (most recent call last):


File "test_sel.py", line 1, in ?
raise IndexError, ’Texto explicativo.’
IndexError: Texto explicativo.

Y podemos crear nuestros propios ((tipos)) de excepción definiendo una nueva clase que hereda de la
clase Exception.

A.7. Funciones
A.7.1. Funciones con nombre
Las funciones se definen con la palabra def seguida del identificador de función, una lista de parámetros
encerrados entre paréntesis y separados por comas y un bloque (indentado) que describe su cuerpo. Para
invocar una función basta con usar su identificador y suministrar los argumentos separados por comas y
encerrados en un par de paréntesis. El paso de parámetros se realiza por referencia a objeto. A efectos
prácticos podemos considerar que los valores escalares se pasan por valor y el resto se pasa por referencia:
1 def myfunction(a, b):
2 a += 1
3 b.append(0)
4

5 x=1
6 y = [2, 1]
7 myfunction(x, y)

8 print x, y

1 [2, 1, 0]

El valor devuelto por una función se indica con la sentencia return, que finaliza la activación de la
función tan pronto se ejecuta:
1 def contains(sequence, item):
2 for element in sequence:
3 if item == element:
4 return True
5 return False
6

7 print contains([1,2,3,5,7,11,13], 5)

True

La asociación entre argumentos en la invocación a una función y los parámetros de la definición es


posicional. Existe una forma alternativa de establecer esta asociación: haciendo alusión al identificador de
cada parámetro para ((asignarle)) un valor.
1 def contains(sequence, item):
2 for element in sequence:
3 if item == element:
4 return True
5 return False
6

7 print contains(item=3, sequence=[1,2,3,5,7,11,13])

Apuntes de Algorı́tmica A-11


A.7 Funciones 2004/09/24-15:53

True

Se pueden definir parámetros con valor por defecto. En la definición de la función el identificador del
parámetro se acompaña del sı́mbolo ((=)) y una expresión con el valor por defecto. Si en la llamada no
proporcionamos un valor al argumento, éste toma el valor por defecto:
1 def multiply(value, factor=2):
2 return value * factor
3

4 print multiply(3, 3), multiply(3)

9 6

No es posible alternar parámetros con y sin valor por defecto en la definición de una función: todos los
parámetros deben llevar valor por defecto a partir del punto en el que aparece uno.
Al invocar o definir una función siempre debe proporcionarse, entre paréntesis, la relación de parámet-
ros. Si no hay parámetros o si todos tienen valor por defecto y se desea usar éste, los paréntesis no con-
tendrán nada, pero deben aparecer igualmente.
Las funciones son objetos de primera clase a los que se puede acceder por su identificador. Es posible,
pues, suministrar un función como argumento en la llamada a otra o almacenar funciones en variables,
listas, diccionario, etc.
1 def summation(a, b, f ):
2 s=0
3 for i in range(a, b+1):
4 s += f (i)
5 return s
6

7 def square(x):
8 return x*x
9

10 def cube(x):
11 return x*x*x
12

13 functions = [square, cube]


14

15 for function in functions:


16 print summation(1, 3, function)

14
36

A.7.2. Algunas funciones predefinidas


Python ofrece varias funciones predefinidas. Entre ellas tenemos:
abs(value): valor absoluto.
cmp(x, y): devuelve un valor negativo si x < y, cero si x = y y un valor positivo si x > y.
divmod(a, b): devuelve un tupla con el cociente (a / b) y el resto (a % b).
Se puede consultar la relación completa en la sección 2.1 de la referencia de bibliotecas de Python, que es
parte de la documentación estándar.

A.7.3. Funciones anónimas


En ocasiones hemos de suministrar funciones como argumentos en la llamada a otras funciones y resul-
ta tedioso definirlas previamente. Las funciones anónimas o lambda-funciones son funciones sencillas
(básicamente expresiones parametrizadas) que no se asocian a identificador alguno. Para definirlas se usa la
palabra reservada lambda con uno o más identificadores separados por comas (los parámetros), dos puntos
y una expresión.

A-12 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

1 def summation(a, b, f ):
2 s=0
3 for i in range(a, b+1):
4 s += f (i)
5 return s
6

7 print summation(1, 3, lambda x: x*x)

14

Las lambda-funciones resultan útiles para, por ejemplo, ordenar con diferentes criterios de ordenación
mediante funciones predefinidas. La función sorted, por ejemplo, ordena una secuencia de elemento y
permite indicar la clave de ordenación mediante el parámetro key, que es una función que se aplica a cada
ı́tem antes de compararlo con otros:

1 names = [’Juan’, ’Ana’, ’Luisa’, ’Federico’, ’Adriana’]


2 print sorted(names)
3 print sorted(names, key=lambda x: len(x))

4 print sorted(names, key=lambda x: x[0])

[’Adriana’, ’Ana’, ’Federico’, ’Juan’, ’Luisa’]


[’Ana’, ’Juan’, ’Luisa’, ’Adriana’, ’Federico’]
[’Ana’, ’Adriana’, ’Federico’, ’Juan’, ’Luisa’]

A.8. Clases
A.8.1. Definición de clases e instanciación de objetos
Python es un lenguaje orientado a objetos y permite definir clases e instanciar objetos a partir de dichas
definiciones. Un bloque encabezado por una sentencia class es una definición de clase. Las funciones que
se definen en el bloque son sus métodos (o ((funciones miembro)), según la nomenclatura de C++).
Ciertos identificadores corresponden a métodos especiales. El constructor, por ejemplo, tiene por iden-
tificador __init__ .

1 class Person:
2 def init (self , name, age):
3 self .name = name
4 self .age = age
5

6 def last name(self ):


7 return self .name.split()[-1]
8

9 somebody = Person(’Juan Nadie’, 35)


10 print somebody.name, somebody.age
11 print ’Apellido:’, somebody.last name()

Juan Nadie 35
Apellido: Nadie

Nótese que el primer parámetro de los métodos es especial y suele usarse el identificador self . Se trata
de una referencia al propio objeto y proporciona un modo de acceso a los atributos y métodos del mismo.
El parámetro self es asimilable al puntero this de C++. En Python, self es, obligatoriamente, el primer
parámetro de los métodos convencionales y a través suyo puede una instancia acceder a sus atributos y
métodos.

A.8.2. Algunos métodos especiales


Ciertos métodos cuyo identificador empieza y acaba con doble subrayado pueden ser invocados de modo
especial. He aquı́ los que usamos en el texto:

Apuntes de Algorı́tmica A-13


A.8 Clases 2004/09/24-15:53

__contains__ (self , item): Se usa para determinar la pertenencia de item al objeto. Se puede invocar
con el operador in.
__len__ (self ): Proporciona la longitud del objeto (en el caso de una secuencia, por ejemplo, el
número de elementos que la forman). Se invoca con la función len.
__getitem__ (self , key): Acceso al objeto con indexación para consulta. Se invoca con el operador
de indexación.
__setitem__ (self , key, value): Acceso al objeto con indexación para asignación. Se invoca con el
operador de indexación sobre un objeto que aparece en la parte izquierda de una asignación.
__iter__ (self ): Iterador que recorre los elementos de la estructura.
__getattr__ (self , id): Acceso al atributo id de un objeto para su consulta. Se invoca con el operador
de indexación.
__setattr__ (self , id, value): Acceso al atributo id de un objeto para asignación de un valor. Se
invoca con el operador de indexación sobre un objeto que aparece en la parte izquierda de una asig-
nación.
1 class MultiSet:
2 def init (self ):
3 self .content = {}
4

5 def add(self , item):


6 try:
7 self .content[item] += 1
8 except KeyError:
9 self .content[item] = 1
10

11 def len (self ):


12 total = 0
13 for key in self .content:
14 total += self .content[key]
15 return total
16

17 def contains (self , item):


18 return item in self .content
19

20 def getitem (self , item):


21 return self .content[item]
22

23 def setitem (self , item, value):


24 self .content[item] = value
25

26 A = MultiSet()
27 for i in 2, 3, 3, 3, 3, 4, 4, 6: A.add(i)
28 print len(A)

29 print 3 in A, A[3]

30 A[3] = 2

31 print A[3]

8
True 4
2

A.8.3. Herencia
Es posible definir una clase a partir de otra, heredando sus atributos y métodos. Al definir la clase basta con
acompañar al identificador de la clase con el de la clase (o clases) padre encerrado entre paréntesis. Python
permite tomar por clase padre a tipos básicos, como las listas o los diccionarios:

A-14 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

1 class MyList(list):
2 def min and max(self ):
3 return min(self ), max(self )
4

5 a = MyList()
6 a.extend([5, 2, 10, 6])
7 print a

8 print a.min and max()

[5, 2, 10, 6]
(2, 10)

La nueva clase puede redefinir métodos del padre.


Si se define un constructor para la nueva clase y se desea que el constructor de la clase padre se ejecute,
se debe invocar explı́citamente:

1 class A:
2 def init (self , n):
3 self .n = n
4

5 class B(A):
6 def init (self , n, m):
7 A. init (self , n)
8 self .m = m
9

10 b = B(2,3)
11 print b.n, b.m

2 3

A.8.4. Creación de alias para métodos


Es posible asociar más de un identificador a un mismo método. Basta para ello con asignar, en el cuerpo de
la clase, un identificador existente al identificador alias:

1 class A:
2 def init (self , n):
3 self .n = n
4

5 def my method(self , a):


6 return self .n * a
7

8 an alias = my method
9

10 a = A(2)
11 print a.my method(4), a.an alias(4)

8 8

A.9. Módulos
Un módulo es una colección de funciones, clases, variables, etc. que podemos utilizar desde un progra-
ma. Hay una gran colección de módulos disponible con la distribución estándar de Python. El módulo
math, por ejemplo, ofrece implementaciones de las funciones matemáticas y define algunas constantes con
aproximaciones a π y e.
La sentencia import seguida del nombre del módulo (sin extensión) da acceso a los objetos definidos
en él. Un objeto importado pasa a estar accesible desde el programa o módulo que lo importa, pero a través
del identificador del módulo, el operador punto y el identificador del objeto en cuestión:

Apuntes de Algorı́tmica A-15


A.10 Iteradores y generadores 2004/09/24-15:53

1 import math
2

3 print math.pi, math.sin(math.pi/3)

3.14159265359 0.866025403784

Se puede importar un solo objeto de un módulo con una sentencia from módulo import object. En ese
caso, se puede usar directamente el identificador del objeto:

1 from math import sin


2

3 print sin(0)

0.0

Se puede importar con una sola sentencia from-import más de un objeto: basta con separarlos con
comas.

1 from math import sin, pi


2

3 print sin(pi/2)

1.0

Hay una forma especial de la sentencia from-import para importar el contenido completo de un módu-
lo:

1 from math import *


2

3 print sin(pi/4)

0.707106781187

A.10. Iteradores y generadores


Es frecuente que surja la necesidad de recorrer todos los elementos de una colección de datos. Python
permite definir iteradores, es decir, objetos que permiten efectuar estos recorridos. C++ ofrece una fun-
cionalidad equivalente a través de los iteradores para el recorrido de estructuras de datos de la STL.
Los generadores son objetos que proporcionan nuevos valores con cada llamada a un método propio sin
que dichos valores formen, necesariamente, parte de una estructura de datos.
Muchas funciones de las bibliotecas Python permiten recorrer transparentemente colecciones de datos
y funcionar sobre secuencias de datos generados al vuelo gracias a los iteradores y generadores. Un objeto
que para que se ha definido el protocolo de los iteradores (y ello incluye a los generadores) es un iterable.

A.10.1. Iterables
Como ya hemos visto, las listas Python son iterables y, por tanto, sus elementos pueden recorrerse con un
bucle:
1 for item in [0, 4, 16, 36, 64]:
2 print item,
3 print

0 4 16 36 64

La función enumerate permite recorrer los elementos de una lista y conocer, para cada uno, su ı́ndice:
1 for index, item in enumerate([i**2 for i in range(10) if i % 2 == 0]):
2 print (index, item),
3 print

A-16 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

(0, 0) (1, 4) (2, 16) (3, 36) (4, 64)

Las claves de un diccionario pueden recorrerse con un bucle, aunque se debe tener presente que el orden
de recorrido es arbitrario:

1 a dict = dict([(’a’,1), (’b’, 2), (’c’, 3)])


2 for k in a dict:
3 print k, a dict[k]

a 1
c 3
b 2

También son iterables las cadenas (se recorren carácter a carácter) y los ficheros (se recorren lı́nea a
lı́nea).

A.10.2. Iteradores
Una estructura de datos es iterable si es capaz de proporcionar un iterador, esto es, un objeto capaz de
efectuar un recorrido de la estructura paso a paso. Si invocamos iter sobre una lista obtenemos un iterador:

1 a = iter([1,2,3])
2 print a

<listiterator object at 0x402a39cc>

El iterador permite recorre los elementos de la estructura de datos mediante sucesivas invocaciones al
método next. Una vez el recorrido finaliza, next provoca una excepción StopIteration:

1 iterator = iter([1,2,3])
2 print iterator.next()
3 print iterator.next()

4 print iterator.next()

5 print iterator.next()

1
2
3
E Traceback (most recent call last):
File "test_dict_3.py", line 5, in ?
print iterator.next()
StopIteration

Al recorrer una serie de valores con un bucle for-in podemos usar la expresión idiomática for i in range(n).
Esta construcción es espacialmente ineficiente, pues construye una lista con n elementos para, inmediata-
mente, construir un iterador con el que recorrerla. La función xrange permite efectuar el mismo recorrido
sin construir explı́citamente la lista:

1 for element in xrange(3):


2 print element

0
1
2

El iterable que devuelve xrange usa un simple contador y una par de variables (el lı́mite y el incremento)
para generar la secuencia de valores.

Apuntes de Algorı́tmica A-17


A.10 Iteradores y generadores 2004/09/24-15:53

A.10.3. Generadores
Un generador es un objeto que proporciona un nuevo valor con cada llamada al método next. Podemos
definir fácilmente un generador mediante una función que hace uso de la sentencia yield. La llamada a la
función devuelve un generador sobre el que cada llamada al método next devuelve el valor que acompaña
a palabra clave yield. El generador recuerda el estado entre llamadas a next. Podemos usar generadores en
bucles for-in.

1 def n squares(n):
2 for i in xrange(n):
3 yield i*i
4

5 a = n squares(3)
6 print a.next(), a.next(), a.next()
7

8 for i in n squares(8):
9 print i,
10 print

0 1 4
0 1 4 9 16 25 36 49

Es posible definir expresiones que devuelven un iterador: las expresiones generatrices, similares a las
listas especificadas por comprensión.

1 iterator = (n*n for n in xrange(3))


2 print iterator.next(), iterator.next(), iterator.next()

0 1 4

A.10.4. Algunas funciones predefinidas que actúan sobre iterables


Python ofrece varias funciones predefinidas. Entre ellas tenemos:

min(iterable): valor mı́nimo de una secuencia.

max(iterable): valor máximo de una secuencia.

sum(iterable): suma de todos los valores de una secuencia.

sorted(iterable): devuelve una lista con los elementos del iterable ordenados.

Podemos construir una lista con todos los valores y aplicar la función min:

1 print min([x-x**3 for x in xrange(10)])

-720

Si actuamos ası́, estamos reservando memoria para cada uno de los elementos y la liberamos inmediata-
mente. Podemos reescribir esta sentencia haciendo uso de expresiones generatrices:

1 print min(x-x**3 for x in xrange(10))

-720

La diferencia sintáctica entre esta sentencia y la anterior es mı́nima: hemos eliminado los corchetes que
rodean al argumento. El consumo de memoria de esta otra versión es constante.

A-18 Apuntes de Algorı́tmica



c 2003, 2004 A. Marzal, M.J. Castro y P. Aibar A Python

A.11. Ficheros
Los ficheros se abren con la función predefinida open o file. El primer parámetro es la ruta del fichero y
el segundo indica el modo de apertura. Se usa ’w’ para escritura, ’r’ para lectura y ’a’ para adición. El
valor por defecto del segundo parámetro es ’r’.
Por defecto se considera que los ficheros son de texto. Son iterables y, si están abiertos en modo lectura,
se recorren lı́nea a lı́nea con un bucle for-in. El método write permite escribir una cadena de texto arbitraria
en un fichero abierto para escritura. Un fichero abierto se cierra con el método close.

1 f = file(’basura’, ’w’)
2 f .write(’una lı́nea\ny otra\n’)
3 f .write(’una más\n’)

4 f .close()

6 for line in file(’basura’):


7 print line,

una lı́nea
y otra
una más

Apuntes de Algorı́tmica A-19

Вам также может понравиться