You are on page 1of 408

Introduccin

a la programacin
con Python 3
Andrs Marzal Var
Isabel Gracia Luengo
Pedro Garca Sevilla

Departament de Llenguatges i Sistemes


Informtics
Codis dassignatures EI1003 i MT1003

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

Edita: Publicacions de la Universitat Jaume I. Servei de Comunicaci i Publicacions


Campus del Riu Sec. Edifici Rectorat i Serveis Centrals. 12071 Castell de la Plana
http://www.tenda.uji.es e-mail: publicacions@uji.es
Collecci Sapientia 93
www.sapientia.uji.es
Primera edici, 2014
ISBN: 978-84-697-1178-1
Publicacions de la Universitat Jaume I s una editorial membre de lune,
cosa que en garanteix la difusi de les obres en els mbits nacional i internacional. www.une.es

Reconeixement-CompartirIgual
CC BY-SA
Aquest text est subjecte a una llicncia Reconeixement-CompartirIgual de Creative Commons, que permet copiar, distribuir i comunicar pblicament lobra sempre que sespecifique
lautor i el nom de la publicaci fins i tot amb objectius comercials i tamb permet crear obres
derivades, sempre que siguen distribudes amb aquesta mateixa llicncia.
http://creativecommons.org/licenses/by-sa/3.0/legalcode

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice general
Prefacio

1. Introduccin
1.1. Computadores . . . . . . . . . . . . . . . . . . . . . . .
1.2. Codificacin de la informacin . . . . . . . . . . . . . .
1.3. Programas y lenguajes de programacin . . . . . . . .
1.3.1. Cdigo de mquina . . . . . . . . . . . . . . . .
1.3.2. Lenguaje ensamblador . . . . . . . . . . . . . .
1.3.3. Un programa diferente para cada ordenador?
1.3.4. Lenguajes de programacin de alto nivel . . .
1.3.5. Compiladores e intrpretes . . . . . . . . . . .
1.3.6. Python . . . . . . . . . . . . . . . . . . . . . . .
1.3.7. Java . . . . . . . . . . . . . . . . . . . . . . . . .
1.4. Ms all de los programas: algoritmos . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

11
11
12
16
17
20
20
21
22
23
26
26

3. Programas
3.1. Tu primer programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1.1. Instalar y preparar Eclipse para el trabajo con la extensin Pydev
3.1.2. Nuestro primer programa . . . . . . . . . . . . . . . . . . . . . . . . .
3.2. Ejecucin de programas desde la lnea de rdenes . . . . . . . . . . . . . .
3.3. Entrada/salida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.1. Lectura de datos de teclado . . . . . . . . . . . . . . . . . . . . . . . .
3.3.2. Ms sobre la funcin print . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

67
67
67
75
77
77
78
80

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

2. Una calculadora avanzada


2.1. Sesiones interactivas . . . . . . . . . . . . . . . . . . . . . .
2.1.1. Los operadores aritmticos . . . . . . . . . . . . . .
2.1.2. Errores de tecleo y excepciones . . . . . . . . . . .
2.2. Tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.1. Tipos entero y flotante . . . . . . . . . . . . . . . . .
2.2.2. El tipo de datos booleano (y sus operadores) . . .
2.3. Literales de entero . . . . . . . . . . . . . . . . . . . . . . . .
2.4. Variables y asignaciones . . . . . . . . . . . . . . . . . . .
2.4.1. Asignaciones con operador . . . . . . . . . . . . . .
2.4.2. Variables no inicializadas . . . . . . . . . . . . . . .
2.5. El tipo de datos cadena . . . . . . . . . . . . . . . . . . . .
2.6. Funciones predefinidas . . . . . . . . . . . . . . . . . . . . .
2.6.1. Algunas funciones sobre valores numricos . . . .
2.6.2. Dos funciones bsicas para cadenas: ord y chr . .
2.7. Mdulos e importacin de funciones y variables . . . . . .
2.7.1. El mdulo math . . . . . . . . . . . . . . . . . . . . .
2.7.2. Otros mdulos de inters . . . . . . . . . . . . . . .
2.8. Mtodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.8.1. Unos mtodos sencillos para manipular cadenas. . .
2.8.2. . . . y uno mucho ms complejo: format . . . . . . .

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

31
31
32
39
40
41
42
46
47
51
51
52
54
54
57
58
58
61
61
61
62

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

3.4. Sobre la legibilidad de los


3.4.1. Algunos convenios
3.4.2. Comentarios . . . .
3.5. Grficos de tortuga . . .

programas
. . . . . . .
. . . . . . .
. . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

4. Estructuras de control
4.1. Sentencias condicionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1. Un programa ilustrativo: resolucin de ecuaciones de primer grado
4.1.2. La sentencia condicional if . . . . . . . . . . . . . . . . . . . . . . . .
4.1.3. Sentencias condicionales anidadas . . . . . . . . . . . . . . . . . . .
4.1.4. Otro ejemplo: resolucin de ecuaciones de segundo grado . . . . .
4.1.5. En caso contrario (else) . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.6. Una estrategia de diseo: refinamientos sucesivos . . . . . . . . . .
4.1.7. Un nuevo refinamiento del programa de ejemplo . . . . . . . . . . .
4.1.8. Otro ejemplo: mximo de una serie de nmeros . . . . . . . . . . . .
4.1.9. Evaluacin con cortocircuitos . . . . . . . . . . . . . . . . . . . . . . .
4.1.10. Un ltimo problema: mens de usuario . . . . . . . . . . . . . . . . .
4.1.11. Una forma compacta para estructuras condicionales mltiples (elif)
4.2. Sentencias iterativas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.1. La sentencia while . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.2. Un problema de ejemplo: clculo de sumatorios . . . . . . . . . . . .
4.2.3. Otro programa de ejemplo: requisitos en la entrada . . . . . . . . .
4.2.4. Mejorando el programa de los mens . . . . . . . . . . . . . . . . . .
4.2.5. El bucle for in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.6. for in como forma compacta de ciertos while . . . . . . . . . . . . .
4.2.7. Nmeros primos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.8. Rotura de bucles: break . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.9. Anidamiento de estructuras . . . . . . . . . . . . . . . . . . . . . . . .
4.3. Captura y tratamiento de excepciones . . . . . . . . . . . . . . . . . . . . . .
4.4. Algunos ejemplos grficos . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.4.1. Un graficador de funciones. . . . . . . . . . . . . . . . . . . . . . . . .
4.4.2. Una animacin: simulacin gravitacional . . . . . . . . . . . . . . . .
4.5. Una reflexin final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

5. Tipos estructurados: secuencias


5.1. Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.1. Lo que ya sabemos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.2. Escapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.3. Longitud de una cadena . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.4. Indexacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.5. Recorrido de cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.6. Un ejemplo: un contador de palabras . . . . . . . . . . . . . . . . . . .
5.1.7. Otro ejemplo: un programa de conversin de binario a decimal . . . .
5.1.8. A vueltas con las cadenas: inversin de una cadena . . . . . . . . . .
5.1.9. Subcadenas: el operador de corte . . . . . . . . . . . . . . . . . . . . .
5.1.10. Una aplicacin: correo electrnico personalizado . . . . . . . . . . .
5.1.11. Referencias a cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2. Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.1. Cosas que, sin darnos cuenta, ya sabemos sobre las listas . . . . . .
5.2.2. Comparacin de listas . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.3. El operador is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.4. Modificacin de elementos de listas . . . . . . . . . . . . . . . . . . . .
5.2.5. Mutabilidad, inmutabilidad y representacin de la informacin
memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.6. Adicin de elementos a una lista . . . . . . . . . . . . . . . . . . . . .
5.2.7. Lectura de listas por teclado . . . . . . . . . . . . . . . . . . . . . . . .
5.2.8. Borrado de elementos de una lista . . . . . . . . . . . . . . . . . . . .
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
. .
en
. .
. .
. .
. .

.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.

81
82
83
84

95
95
95
97
100
103
104
106
108
110
115
116
118
119
120
125
127
129
132
135
136
142
144
146
148
148
152
159

161
161
161
162
165
166
167
169
173
175
176
178
180
185
186
189
190
191
192
194
197
199

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

5.2.9. Pertenencia de un elemento a una lista


5.2.10. Ordenacin de una lista . . . . . . . . . .
5.3. De cadenas a listas y viceversa . . . . . . . . . .
5.4. Matrices . . . . . . . . . . . . . . . . . . . . . . . .
5.4.1. Sobre la creacin de matrices . . . . . .
5.4.2. Lectura de matrices . . . . . . . . . . . .
5.4.3. Qu dimensin tiene una matriz? . . . .
5.4.4. Operaciones con matrices . . . . . . . . .
5.4.5. El juego de la vida . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

202
203
208
210
211
214
214
215
219

6. Funciones
231
6.1. Uso de funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
6.2. Definicin de funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
6.2.1. Definicin y uso de funciones con un solo parmetro . . . . . . . . . . . . 232
6.2.2. Definicin y uso de funciones con varios parmetros . . . . . . . . . . . . . 242
6.2.3. Definicin y uso de funciones sin parmetros . . . . . . . . . . . . . . . . . 244
6.2.4. Procedimientos: funciones sin devolucin de valor . . . . . . . . . . . . . . 248
6.2.5. Funciones que devuelven varios valores mediante una lista . . . . . . . . . 253
6.3. Variables locales y variables globales . . . . . . . . . . . . . . . . . . . . . . . . . . 255
6.4. El mecanismo de las llamadas a funcin . . . . . . . . . . . . . . . . . . . . . . . . . 264
6.4.1. La pila de llamadas a funcin y el paso de parmetros . . . . . . . . . . . 264
6.4.2. Paso del resultado de expresiones como argumentos . . . . . . . . . . . . . 269
6.4.3. Ms sobre el paso de parmetros . . . . . . . . . . . . . . . . . . . . . . . . 270
6.4.4. Acceso a variables globales desde funciones . . . . . . . . . . . . . . . . . . 278
6.5. Un ejemplo: Memorin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
6.6. Ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
6.6.1. Integracin numrica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
6.6.2. Aproximacin de la exponencial de un nmero real . . . . . . . . . . . . . . 295
6.6.3. Clculo de nmeros combinatorios . . . . . . . . . . . . . . . . . . . . . . . . 300
6.6.4. El mtodo de la biseccin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
6.7. Diseo de programas con funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
6.7.1. Ahorro de tecleo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
6.7.2. Mejora de la legibilidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
6.7.3. Algunos consejos para decidir qu debera definirse como funcin: anlisis
descendente y ascendente . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
6.8. Recursin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
6.8.1. Clculo recursivo del factorial . . . . . . . . . . . . . . . . . . . . . . . . . . 307
6.8.2. Clculo recursivo del nmero de bits necesarios para representar un nmero 310
6.8.3. Los nmeros de Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
6.8.4. El algoritmo de Euclides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
6.8.5. Las torres de Hanoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
6.8.6. Recursin indirecta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
6.8.7. Grficos fractales: copos de nieve de Von Koch . . . . . . . . . . . . . . . . 320
6.9. Mdulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
6.9.1. Un mdulo muy sencillo: mnimo y mximo . . . . . . . . . . . . . . . . . . 326
6.9.2. Un mdulo ms interesante: gravedad . . . . . . . . . . . . . . . . . . . . . 327
6.10. Documentacin del cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
6.10.1. Otro mdulo: clculo vectorial . . . . . . . . . . . . . . . . . . . . . . . . . . 331
6.10.2. Un mdulo para trabajar con polinomios . . . . . . . . . . . . . . . . . . . . 334
6.10.3. Un mdulo con utilidades estadsticas . . . . . . . . . . . . . . . . . . . . . 337
6.10.4. Un mdulo para clculo matricial . . . . . . . . . . . . . . . . . . . . . . . . 338
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

7. Tipos estructurados: clases y diccionarios


7.1. Tipos de datos a medida . . . . . . . . . . . . . . . . . . . . .
7.1.1. Lo que sabemos hacer . . . . . . . . . . . . . . . . . . .
7.1.2. . . . pero sabemos hacerlo mejor . . . . . . . . . . . . .
7.1.3. Lo que haremos: usar tipos de datos a medida . . .
7.2. Definicin de clases en Python . . . . . . . . . . . . . . . . . .
7.2.1. Referencias y objetos . . . . . . . . . . . . . . . . . . .
7.2.2. Un ejemplo: gestin de calificaciones de estudiantes .
7.3. Algunas clases de uso comn . . . . . . . . . . . . . . . . . . .
7.3.1. La clase fecha . . . . . . . . . . . . . . . . . . . . . . . .
7.3.2. Colas y pilas . . . . . . . . . . . . . . . . . . . . . . . .
7.3.3. Colas de prioridad . . . . . . . . . . . . . . . . . . . . .
7.3.4. Conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . .
7.4. Un ejemplo completo: gestin de un videoclub . . . . . . . . .
7.4.1. Videoclub bsico . . . . . . . . . . . . . . . . . . . . . .
7.4.2. Un videoclub ms realista . . . . . . . . . . . . . . . . .
7.4.3. Listado completo . . . . . . . . . . . . . . . . . . . . . .
7.4.4. Extensiones propuestas . . . . . . . . . . . . . . . . . .
7.4.5. Algunas reflexiones . . . . . . . . . . . . . . . . . . . . .
7.5. Diccionarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.5.1. Creacin de diccionarios . . . . . . . . . . . . . . . . .
7.5.2. Consulta en diccionarios . . . . . . . . . . . . . . . . .
7.5.3. Recorrido de diccionarios . . . . . . . . . . . . . . . . .
7.5.4. Borrado de elementos . . . . . . . . . . . . . . . . . . .
7.5.5. Una aplicacin: un listn telefnico . . . . . . . . . . .
7.5.6. Un contador de palabras . . . . . . . . . . . . . . . . .
7.5.7. Rediseo del programa del videoclub con diccionarios

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

8. Ficheros
8.1. Generalidades sobre ficheros . . . . . . . . . . . . . . . . . . . . . . . .
8.1.1. Sistemas de ficheros: directorios y ficheros . . . . . . . . . . .
8.1.2. Rutas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1.3. Montaje de unidades . . . . . . . . . . . . . . . . . . . . . . . . .
8.2. Ficheros de texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2.1. El protocolo de trabajo con ficheros: abrir, leer/escribir, cerrar
8.2.2. Lectura de ficheros de texto lnea a lnea . . . . . . . . . . . .
8.2.3. Lectura carcter a carcter . . . . . . . . . . . . . . . . . . . . .
8.2.4. Otra forma de leer lnea a lnea . . . . . . . . . . . . . . . . . .
8.2.5. Escritura de ficheros de texto . . . . . . . . . . . . . . . . . . . .
8.2.6. Aadir texto a un fichero . . . . . . . . . . . . . . . . . . . . . .
8.2.7. Cosas que no se pueden hacer con ficheros de texto . . . . . .
8.2.8. Un par de ficheros especiales: el teclado y la pantalla . . . .
8.3. Una aplicacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.4. Texto con formato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

341
341
341
342
344
346
349
351
354
355
358
360
361
363
364
370
372
378
378
379
379
379
380
381
381
383
384
387
387
387
388
389
390
390
390
395
397
398
400
402
402
403
407

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

Prefacio

Introduccin a la programacin con Python 3 desarrolla el temario de la asignatura Programacin I que se imparte durante el primer semestre de primer curso en los grados en
Ingeniera Informtica y en Matemtica Computacional de la Universitat Jaume I. En ella se
pretende ensear a programar y se utiliza Python como primer lenguaje de programacin.
Por qu Python? Python es un lenguaje de muy alto nivel que permite expresar algoritmos
de forma casi directa (ha llegado a considerarse pseudocdigo ejecutable) y hemos comprobado
que se trata de un lenguaje particularmente adecuado para la enseanza de la programacin.
Esta impresin se ve corroborada por la adopcin de Python como lenguaje introductorio en
otras universidades. Otros lenguajes, como Java, C o C#, exigen una gran atencin a multitud
de detalles que dificultan la implementacin de algoritmos a un estudiante que se enfrenta
por primera vez al desarrollo de programas. No obstante, son lenguajes de programacin de
referencia y deberan formar parte del currculum de todo informtico. Aprender Python como
primer lenguaje permite estudiar las estructuras de control y de datos bsicas con un alto
nivel de abstraccin y, as, entender mejor qu supone exactamente la mayor complejidad de
la programacin en otros lenguajes y hasta qu punto es mayor el grado de control que nos
otorgan. Por ejemplo, una vez se han estudiado listas en Python, su implementacin en otros
lenguajes permite al estudiante no perder de vista el objetivo ltimo: construir una entidad con
cierto nivel de abstraccin usando las herramientas concretas proporcionadas por el lenguaje. De
algn modo, pues, Python ayuda al aprendizaje posterior de otros lenguajes, lo que proporciona
al estudiante una visin ms rica y completa de la programacin. Las similitudes y diferencias
entre los distintos lenguajes permiten al estudiante inferir ms fcilmente qu es fundamental y
qu accesorio o accidental al disear programas en un lenguaje de programacin cualquiera.
Y por qu otro libro de texto introductorio a la programacin? Ciertamente hay muchos
libros que ensean a programar desde cero. Creemos que este texto se diferencia de ellos en la
forma en que se exponen y desarrollan los contenidos. Hemos procurado adoptar siempre el punto
de vista del estudiante y presentar los conceptos y estrategias para disear programas bsicos
paso a paso, incrementalmente. La experiencia docente nos ha ido mostrando toda una serie
de lneas de razonamiento inapropiadas, errores y vicios en los que caen muchos estudiantes.
El texto intenta exponer, con mayor o menor fortuna, esos razonamientos, errores y vicios para
que el estudiante los tenga presentes y procure evitarlos. As, en el desarrollo de algunos
programas llegamos a ofrecer versiones errneas para, acto seguido, estudiar sus defectos y
mostrar una versin corregida. El libro est repleto de cuadros que pretenden profundizar en
aspectos marginales, llamar la atencin sobre algn extremo, ofrecer algunas pinceladas de
historia o, sencillamente, desviarse de lo sustancial con alguna digresin que podra resultar
motivadora para el estudiante.
Queremos aprovechar para dar un consejo al estudiantado que no nos cansamos de repetir:
es imposible aprender a programar limitndose a leer un texto o a seguir pasivamente una
explicacin en clase (especialmente si el perodo de estudio se concentra en una o dos semanas
antes del examen). Programar al nivel propio de un curso introductorio no es particularmente
difcil, pero constituye una actividad intelectual radicalmente nueva para muchos estudiantes.
Es necesario darse una oportunidad para ir asentando los conocimientos y las estrategias de
diseo de programas (y as, superar el curso). Esa oportunidad requiere tiempo para madurar. . . y
trabajo, mucho trabajo; por eso el texto ofrece ms de cuatrocientos ejercicios. Solo tras haberse
enfrentado a buena parte de ellos se estar preparado para demostrar que se ha aprendido lo
necesario.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Este texto es una actualizacin y revisin del libro Introduccin a la programacin con Python
publicado dentro de la coleccin Sapientia de la Universitat Jaume I. Las principales diferencias
con respecto a la versin anterior son:
Se ha actualizado la versin del lenguaje empleado. La versin anterior del libro se escribi
para Python 2 (en concreto, para la versin 2.3). Desde entonces, el lenguaje ha seguido
dos ramas de desarrollo diferentes: Python 2 y Python 3. Este nuevo texto utiliza Python 3,
lo que, adems de modificar contenidos, ha supuesto reescribir todos los programas de
ejemplo. Aunque en el momento de escribir estas lneas ya se ha publicado la versin 3.4
de Python, todos los programas de ejemplo incluidos en este libro deberan funcionar para
cualquier versin a partir de la 3.1.
Tambin hemos cambiado el entorno de desarrollo y la librera grfica empleada. La
versin anterior del libro usaba un entorno de desarrollo propio (PythonG) que, a su
vez, incorporaba una sencilla librera grfica. Ahora se utiliza un entorno de desarrollo
estndar y muy potente, Eclipse, que podr seguir siendo usado por los estudiantes en
otras asignaturas y con otros lenguajes de programacin. En cuanto a la parte grfica,
ahora se utiliza el mdulo turtle, incorporado al propio lenguaje desde la versin 3.1.
El captulo 7 del libro anterior resultaba un tanto artificial al simular, mediante una librera
propia, el concepto de registro como una versin simplificada del concepto de clase.
Aunque la programacin orientada a objetos se estudia en detalle en otras asignaturas
de los grados, hemos considerado ms acertado reescribir este captulo para introducir los
conceptos bsicos de clase y objeto. Adems, se ha incluido tambin un breve apartado
dedicado al estudio de diccionarios.

Por supuesto, hemos corregido erratas (y tambin errores importantes!), hemos aadido nuevos
ejemplos y modificado otros, hemos incorporado nuevos ejercicios y reubicado otros en lugares
que hemos juzgado ms apropiados, etc.

Convenios tipogrficos

Hemos tratado de seguir una serie de convenios tipogrficos a lo largo del texto. Los programas, por ejemplo, se muestran con fondo gris, as:
1

print

Por regla general, las lneas del programa aparecen numeradas a mano izquierda. Esta numeracin tiene por objeto facilitar la referencia a puntos concretos del programa y no debe
reproducirse en el fichero de texto si se copia el programa.
Cuando se quiere destacar el nombre del fichero en el que reside un programa, se indica en
una barra encima del cdigo:
1

print

Cuando un programa contiene algn error grave, aparece un rayo rojo a la izquierda del nombre
del programa:
E
1

rint

Algunos programas no estn completos y, por ello, presentan alguna deficiencia. No obstante,
hemos optado por no marcarlos como errneos cuando estos evolucionan en el curso de la
exposicin.
La informacin que aparece en pantalla se muestra con un tipo de letra monoespaciado. As,
el resultado de ejecutar la versin correcta del programa hola_mundo py se mostrar como:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Las sesiones interactivas del intrprete de Python tambin se muestran con un tipo de letra

monoespaciado. El prompt primario del intrprete Python se muestra con los caracteres
.
y el secundario con
Las expresiones y sentencias que debe teclear el usuario, tanto en el intrprete de Python
como durante la ejecucin de un programa, se destacan en color azul y el retorno de carro se
representa explcitamente con el smbolo :

Agradecimientos

Este texto es fruto de la experiencia docente de todo el profesorado de las asignaturas


Metodologa y tecnologa de la programacin (de las antiguas titulaciones de Ingeniera Informtica e Ingeniera Tcnica en Informtica de Gestin) y Programacin I (de los actuales
grados en Ingeniera Informtica y en Matemtica Computacional) de la Universitat Jaume I y
se ha enriquecido con las aportaciones, comentarios y correcciones de muchos profesores del
Departamento de Lenguajes y Sistemas Informticos: Juan Pablo Aibar Ausina, Rafael Berlanga
Llavori, Antonio Castellanos Lpez, Vctor Manuel Jimnez Pelayo, Mara Dolores Llid Escriv,
David Llorens Piana, Jos Luis Llopis Borrs, Ramn Mollineda Crdenas, Federico Prat Villar
y Juan Miguel Vilar Torres. Para todos ellos, nuestro ms sincero agradecimiento. Finalmente, tambin agradecemos la colaboracin de cuantos nos han hecho llegar sugerencias o han
detectado erratas.
Castelln de la Plana, 28 de julio de 2014
Andrs Marzal Var, Isabel Gracia Luengo y Pedro Garca Sevilla

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Captulo 1

Introduccin

Qu sabes de este asunto? pregunt el Rey a Alicia.


Nada dijo Alicia.
Absolutamente nada? insisti el Rey.
Absolutamente nada dijo Alicia.
Esto es importante dijo el Rey, volvindose hacia los jurados.

Alicia en el pas de las maravillas, Lewis Carroll

El objetivo de este curso es ensearte a programar, esto es, a disear algoritmos y expresarlos como programas escritos en un lenguaje de programacin para poder ejecutarlos en un
computador.
Seis trminos tcnicos en el primer prrafo. No est mal. Vayamos paso a paso: empezaremos
por presentar en qu consiste, bsicamente, un computador.

1.1.

Computadores

El diccionario de la Real Academia define computador electrnico como Mquina electrnica,


analgica o digital, dotada de una memoria de gran capacidad y de mtodos de tratamiento
de la informacin, capaz de resolver problemas matemticos y lgicos mediante la utilizacin
automtica de programas informticos.
La propia definicin nos da indicaciones acerca de algunos elementos bsicos del computador:
la memoria,

y algn dispositivo capaz de efectuar clculos matemticos y lgicos.

La memoria es un gran almacn de informacin. En la memoria guardamos todo tipo de


datos: valores numricos, textos, imgenes, etc. El dispositivo encargado de efectuar operaciones
matemticas y lgicas, que recibe el nombre de Unidad Aritmtico-Lgica (UAL), es como una
calculadora capaz de trabajar con esos datos y producir, a partir de ellos, nuevos datos (el
resultado de las operaciones). Otro dispositivo se encarga de transportar la informacin de la
memoria a la UAL, de controlar a la UAL para que efecte las operaciones pertinentes en el
instante justo y de depositar los resultados en la memoria: la Unidad de Control. El conjunto
que forman la Unidad de Control y la UAL se conoce por Unidad Central de Proceso (o CPU,
del ingls Central Processing Unit).
Podemos imaginar la memoria como un armario enorme con cajones numerados y la CPU
como una persona que, equipada con una calculadora (la UAL), es capaz de buscar operandos
en la memoria, efectuar clculos con ellos y dejar los resultados en la memoria.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2

Memoria

Unidad Central de Proceso

Unidad de Control

Unidad Aritmtico-Lgica

5
6
7
..
.

Utilizaremos un lenguaje ms tcnico: cada uno de los cajones que conforman la memoria
recibe el nombre de celda (de memoria) y el nmero que lo identifica es su posicin o direccin,
aunque a veces usaremos estos dos trminos para referirnos tambin a la correspondiente celda.
Cada posicin de memoria permite almacenar una secuencia de unos y ceros de tamao fijo.
Por qu unos y ceros? Porque la tecnologa actual de los computadores se basa en la sencillez
con que es posible construir dispositivos binarios, es decir, que pueden adoptar dos posibles
estados: encendido/apagado, hay corriente/no hay corriente, cierto/falso, uno/cero. . . Es posible
representar datos tan variados como nmeros, textos, imgenes, etc. con solo unos y ceros? La
respuesta es s (aunque con ciertas limitaciones). Para entenderla mejor, es preciso que nos
detengamos brevemente a considerar cmo se representa la informacin con valores binarios.

1.2.

Codificacin de la informacin

Una codificacin asocia signos con los elementos de un conjunto a los que denominamos
significados. En occidente, por ejemplo, codificamos los nmeros de cero a nueve con el conjunto
de signos {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}. Al hacerlo, ponemos en correspondencia estos smbolos con
cantidades, es decir, con su significado: el smbolo 6 representa a la cantidad seis. El conjunto
de signos no tiene por qu ser finito. Podemos combinar los dgitos en secuencias que ponemos
en correspondencia con, por ejemplo, los nmeros naturales. La sucesin de dgitos 99 forma
un nuevo signo que asociamos a la cantidad noventa y nueve. Los ordenadores solo tienen dos
signos bsicos, {0, 1}, pero se pueden combinar en secuencias, as que no estamos limitados a
solo dos posibles significados.
Una variable que solo puede tomar uno de los dos valores binarios recibe el nombre de bit
(acrnimo del ingls binary digit). Es habitual trabajar con secuencias de bits de tamao fijo.
Una secuencia de 8 bits recibe el nombre de byte (aunque en espaol el trmino correcto es
octeto, este no acaba de imponerse y se usa mucho ms la voz inglesa). Con una secuencia de
8 bits podemos representar 256 (que es el valor de 28 ) significados diferentes. El rango [0, 255]
de valores naturales comprende 256 valores, as que podemos representar cualquiera de ellos
con un patrn de 8 bits. Podramos decidir, en principio, que la correspondencia entre bytes y
valores naturales es completamente arbitraria. As, podramos decidir que la secuencia
representa, por ejemplo, el nmero natural 0 y que la secuencia
representa el valor 3.
Aunque sea posible esta asociacin arbitraria, no es deseable, pues complica enormemente
efectuar operaciones con los valores. Sumar, por ejemplo, obligara a tener memorizada una
tabla que dijera cul es el resultado de efectuar la operacin con cada par de valores, y hay
65.536 pares diferentes!
Los sistemas de representacin posicional permiten establecer esa asociacin entre secuencias de bits y valores numricos naturales de forma sistemtica. Centramos el discurso en
secuencias de 8 bits, aunque todo lo que exponemos a continuacin es vlido para secuencias de otros tamaos1 . El valor
 de una cadena de bits b7 b6 b5 b4 b3 b2 b1 b0 es, en un sistecodifica el valor
ma posicional convencional, 7i=0 bi 2i . As, la secuencia de bits
0 27 + 0 26 + 0 25 + 0 24 + 1 23 + 0 22 + 1 21 + 1 20 = 8 + 2 + 1 = 11. El bit de ms a la
1 Ocho bits ofrecen un rango de valores muy limitado. Es habitual en los ordenadores modernos trabajar con grupos
de 4 bytes (32 bits) u 8 bytes (64 bits).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

izquierda recibe el nombre de bit ms significativo y el bit de ms a la derecha se denomina


bit menos significativo.

1
Cul es el mximo valor que puede representarse con 16 bits y un sistema de representacin posicional como el descrito? Qu secuencia de bits le corresponde?
2

Cuntos bits se necesitan para representar los nmeros del 0 al 18, ambos inclusive?

El sistema posicional es especialmente adecuado para efectuar ciertas operaciones aritmticas. Tomemos por caso la suma. Hay una tabla de sumar en binario que te mostramos a
continuacin:
sumandos

suma

acarreo

El acarreo no nulo indica que un dgito no es suficiente para expresar la suma de dos bits y
que debe aadirse el valor uno al bit que ocupa una posicin ms a la izquierda. Para ilustrar
la sencillez de la adicin en el sistema posicional, hagamos una suma de dos nmeros de 8 bits
usando esta tabla. En este ejemplo sumamos los valores 11 y 3 en su representacin binaria:
+

Empezamos por los bits menos significativos. Segn la tabla, la suma y da con acarreo :
Acarreo

El segundo dgito empezando por la derecha toma el valor que resulta de sumar a y
el acarreo que arrastramos. O sea, y es con acarreo , pero al sumar el acarreo que
arrastramos de la anterior suma de bits, el resultado final es con acarreo :
Acarreo

Ya te habrs hecho una idea de la sencillez del mtodo. De hecho, ya lo conoces bien, pues el
sistema de numeracin que aprendiste en la escuela es tambin posicional, solo que usando diez
dgitos diferentes en lugar de dos, as que el procedimiento de suma es esencialmente idntico.
, o sea, el valor 14:
He aqu el resultado final, que es la secuencia de bits
Acarreo

La circuitera electrnica necesaria para implementar un sumador que acte como el descrito
es extremadamente sencilla.
a)

Calcula las siguientes sumas de nmeros codificados con 8 bits en el sistema posicional:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

b)
c)

Debes tener en cuenta que la suma de dos nmeros de 8 bits puede proporcionar una cantidad
)
que requiere 9 bits. Suma, por ejemplo, las cantidades 255 (en binario de 8 bits es
):
y 1 (que en binario es
Acarreo

( )

El resultado es la cantidad 256, que en binario se expresa con 9 bits, no con 8. Decimos
en este caso que la suma ha producido un desbordamiento. Esta anomala debe ser tenida en
cuenta cuando se usa o programa un ordenador.
Hasta el momento hemos visto cmo codificar valores positivos. Podemos representar tambin
cantidades negativas? La respuesta es s. Consideremos brevemente tres formas de hacerlo. La
primera es muy intuitiva: consiste en utilizar el bit ms significativo para codificar el signo; si
vale , por ejemplo, el nmero expresado con los restantes bits es positivo (con la representacin
es 2 y
posicional que ya conoces), y si vale , es negativo. Por ejemplo, el valor de
es 2. Efectuar sumas con valores positivos y negativos resulta relativamente
el de
complicado si codificamos as el signo de un nmero. Esta mayor complicacin se traslada
tambin a la circuitera necesaria. Mala cosa.
Otra forma de codificar cantidades positivas y negativas es el denominado complemento a
uno. Consiste en lo siguiente: se toma la representacin posicional de un nmero (que debe
poder expresarse con 7 bits) y se invierten todos sus bits si es negativo. La suma de nmeros
codificados as es relativamente sencilla: se efecta la suma convencional y, si no se ha producido
un desbordamiento, el resultado es el valor que se deseaba calcular; pero si se produce un
desbordamiento, la solucin se obtiene sumando el valor 1 al resultado de la suma (sin tener
en cuenta ya el bit desbordado). Vemoslo con un ejemplo. Sumemos el valor 3 al valor 2 en
complemento a uno:
Acarreo

( )

La primera suma ha producido un desbordamiento. El resultado correcto resulta de sumar


una unidad a los 8 primeros bits.
La codificacin en complemento a uno tiene algunas desventajas. Una de ellas es que hay
como
dos formas de codificar el valor 0 (con 8 bits, por ejemplo, tanto
representan el valor 0) y, por tanto, solo podemos representar 255 valores ([127, 127]), en lugar
de 256. Pero el principal inconveniente es la potencial lentitud con que se realizan operaciones
como la suma: cuando se produce un desbordamiento se han de efectuar dos adiciones, es decir,
se ha de invertir el doble de tiempo para completar la operacin.
Una codificacin alternativa (y que es la utilizada en los ordenadores) es la denominada
complemento a dos. Para cambiar el signo a un nmero hemos de invertir todos sus bits y
sumar 1 al resultado. Esta codificacin, que parece poco natural, tiene las ventajas de que solo
hay una forma de representar el valor nulo (el rango de valores representados es [128, 127])
y de que una sola operacin de suma basta siempre para obtener el resultado correcto de una
adicin. Repitamos el ejemplo anterior. Sumemos 3 y 2, pero en complemento a dos:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Acarreo

( )

Si ignoramos el bit desbordado, el resultado es correcto.

a) 4

b) 4

Codifica en complemento a dos de 8 bits los siguientes valores:

c) 0

d) 127
e) 1

f) 1
5

a) 4 + 4

Efecta las siguientes sumas y restas en complemento a dos de 8 bits:

b) 4 + 3

c) 127 128

d) 127 127
e) 1 1
f) 1 2

Bueno, ya hemos hablado bastante acerca de cmo codificar nmeros (aunque ms adelante ofreceremos alguna reflexin acerca de cmo representar valores con parte fraccional).
Preocupmonos por un instante acerca de cmo representar texto. Hay una tabla que pone en
correspondencia 127 smbolos con secuencias de bits y que se ha asumido como estndar. Entre
esos smbolos se encuentran todas las letras del alfabeto ingls, tanto en minscula como en
mayscula, signos de puntuacin y otros que puedes encontrar en el teclado. Es la denominada
tabla ASCII, cuyo nombre corresponde a las siglas de American Standard Code for Information
Interchange. La correspondencia entre secuencias de bits y caracteres determinada por la tabla
es arbitraria, pero aceptada como estndar. La letra a, por ejemplo, se codifica con la secuencia
y la letra A se codifica con
.
de bits

El texto se puede codificar, pues, como una secuencia de bits. Aqu tienes el texto
codificado con la tabla ASCII:
Cuando aparece ese texto en pantalla, no vemos esas secuencias de bits: no entenderamos
nada. En pantalla vemos una sucesin de grficos, uno que corresponde a la letra H, seguido
de otro que corresponde a la letra o. . . Estos grficos son patrones de pxeles almacenados en
la memoria del ordenador y que se muestran en la pantalla. Un bit de valor 0 puede mostrarse
como color blanco y un bit de valor 1 como color negro. La letra H que ves en pantalla, por
ejemplo, podra no ser ms que la visualizacin de este patrn de bits:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

La tabla ASCII al completo

Estos son los valores (en base 10) de cada smbolo en la tabla ASCII:

Los 32 primeros elementos de la tabla corresponden a los denominados caracteres de control y


se disearon para controlar los dispositivos en los que se muestra el texto. La mayor parte de ellos
son obsoletos, pues se concibieron cuando lo normal era que el texto producido por un ordenador
se mostrara en un teletipo, una impresora, tarjetas perforadas o una consola. El carcter
, por
ejemplo, haca sonar la campanita del teletipo (
es abreviatura de bell). En un ordenador de
hoy, ese carcter puede disparar un pitido. El carcter con nmero decimal 32 (en binario
)
es el espacio en blanco ( es abreviatura de space). Del 33 al 47 tenemos un juego de caracteres
variados (signos de puntuacin, el signo del dlar, la almohadilla, algunos operadores matemticos,
etc.). Del 48 al 57 encontramos los dgitos del sistema decimal. Del 58 al 64 hay otros caracteres
especiales (signos de puntuacin, de comparacin y la arroba). Empieza entonces el alfabeto en
maysculas, que va del cdigo 65 al 90). Del 91 al 96 volvemos a encontrar smbolos variados y el
alfabeto en minsculas sigue a estos con los smbolos del 97 al 122. La tabla se completa con otros
cuatro smbolos variados y un ltimo carcter de control: el que representa la accin de borrado de
un carcter (
es abreviatura de delete).

En la memoria del ordenador se dispone de un patrn de bits para cada carcter2 . Cuando
, se muestra en pantalla el patrn de bits correspondiente
se detecta el cdigo ASCII
a la representacin grfica de la H. Truculento, pero eficaz.
No solo podemos representar caracteres con patrones de pxeles: todos los grficos de ordenador son simples patrones de pxeles dispuestos como una matriz.
Como puedes ver, s basta con ceros y unos para codificar la informacin que manejamos en
un ordenador: nmeros, texto, imgenes, etc.

1.3.

Programas y lenguajes de programacin

Antes de detenernos a hablar de la codificacin de la informacin estbamos comentando


que la memoria es un gran almacn con cajones numerados, es decir, identificables con valores
numricos: sus respectivas direcciones. En cada cajn se almacena una secuencia de bits de
tamao fijo. La CPU, el cerebro del ordenador, es capaz de ejecutar acciones especificadas
mediante secuencias de instrucciones. Una instruccin describe una accin muy simple, del
estilo de suma esto con aquello, multiplica las cantidades que hay en tal y cual posicin
de memoria, deja el resultado en tal direccin de memoria, haz una copia del dato de esta
direccin en esta otra direccin, averigua si la cantidad almacenada en determinada direccin
es negativa, etc. Las instrucciones se representan mediante combinaciones particulares de unos
y ceros (valores binarios) y, por tanto, se pueden almacenar en la memoria.
Combinando inteligentemente las instrucciones en una secuencia podemos hacer que la CPU
ejecute clculos ms complejos. Una secuencia de instrucciones es un programa. Si hay una

2 La realidad es cada vez ms compleja. Los sistemas modernos almacenan los caracteres en memoria de otra forma,
pero hablar de ello supone desviarnos mucho de lo que queremos contar.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

instruccin para multiplicar pero ninguna para elevar un nmero al cubo, podemos construir un
programa que efecte este ltimo clculo a partir de las instrucciones disponibles. He aqu,
grosso modo, una secuencia de instrucciones que calcula el cubo a partir de productos:
1) Toma el nmero y multiplcalo por s mismo.

2) Multiplica el resultado de la ltima operacin por el nmero original.

Las secuencias de instrucciones que el ordenador puede ejecutar reciben el nombre de


programas en cdigo de mquina, porque el lenguaje de programacin en el que estn expresadas
recibe el nombre de cdigo de mquina. Un lenguaje de programacin es cualquier sistema de
notacin que permite expresar programas.

1.3.1.

Cdigo de mquina

El cdigo de mquina codifica las secuencias de instrucciones como sucesiones de unos y


ceros que siguen ciertas reglas. Cada familia de ordenadores dispone de su propio repertorio de
instrucciones, es decir, de su propio cdigo de mquina.
Un programa que, por ejemplo, calcula la media de tres nmeros almacenados en las posiciones de memoria 10, 11 y 12, respectivamente, y deja el resultado en la posicin de memoria
13, podra tener el siguiente aspecto expresado de forma comprensible para nosotros:
Memoria

1
2
3
4
5
6
7
..
.

En realidad, el contenido de cada direccin estara codificado como una serie de unos y
ceros, as que el aspecto real de un programa como el descrito arriba podra ser este:
1
2

Memoria

3
4
5
6
7
..
.

La CPU es un ingenioso sistema de circuitos electrnicos capaz de interpretar el significado


de cada una de esas secuencias de bits y llevar a cabo las acciones que codifican. Cuando la
CPU ejecuta el programa empieza por la instruccin contenida en la primera de sus posiciones de
memoria. Una vez ha ejecutado una instruccin, pasa a la siguiente, y sigue as hasta encontrar
una instruccin que detenga la ejecucin del programa.
Supongamos que en las direcciones de memoria 10, 11 y 12 se han almacenado los valores
5, 10 y 6, respectivamente. Representamos as la memoria:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2

Memoria

4
..
.
10

11

12
..
.

10
6

Naturalmente, los valores de las posiciones 10, 11 y 12 estarn codificados en binario, aunque
hemos optado por representarlos en base 10 en aras de una mayor claridad.
La ejecucin del programa procede del siguiente modo. En primer lugar, se ejecuta la instruccin de la direccin 1, que dice que tomemos el contenido de la direccin 10 (el valor 5), lo
sumemos al de la direccin 11 (el valor 10) y dejemos el resultado (el valor 15) en la direccin
de memoria 13. Tras ejecutar esta primera instruccin, la memoria queda as:
1
2

Memoria

4
..
.
10

11

12

13
..
.

10
6

15

A continuacin, se ejecuta la instruccin de la direccin 2, que ordena que se tome el contenido


de la direccin 13 (el valor 15), se sume al contenido de la direccin 12 (el valor 6) y se deposite
el resultado (el valor 21) en la direccin 13. La memoria pasa a quedar en este estado.
1
2

Memoria

4
..
.
10

11

12

13
..
.

10
6

21

Ahora, la tercera instruccin dice que hemos de tomar el valor de la direccin 13 (el valor 21),
dividirlo por 3 y depositar el resultado (el valor 7) en la direccin 13. Este es el estado en que
queda la memoria tras ejecutar la tercera instruccin:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Memoria

1
2
3

4
..
.
10

11

10

12

13

..
.

Y finalmente, la CPU detiene la ejecucin del programa, pues se encuentra con la instruccin
en la direccin 4.

6
Ejecuta paso a paso el mismo programa con los valores 2, 2 y 0 en las posiciones de
memoria 10, 11 y 12, respectivamente.

7
Disea un programa que calcule la media de cinco nmeros depositados en las posiciones de memoria que van de la 10 a la 14 y que deje el resultado en la direccin de memoria 15.
Recuerda que la media x de cinco nmeros x1 , x2 , x3 , x4 y x5 es
x =

5

i=1 xi

x1 + x2 + x3 + x4 + x5
.
5

8
Disea un programa que calcule la varianza de cinco nmeros depositados en las
posiciones de memoria que van de la 10 a la 14 y que deje el resultado en la direccin de
memoria 15. La varianza, que se denota con 2 , es
2

5

i=1 (xi

x)2

donde x es la media de los cinco valores. Supn que existe una instruccin Multiplicar el
contenido de direccin a por el contenido de direccin b y dejar el resultado en direccin c.

Qu instrucciones podemos usar para confeccionar programas? Ya hemos dicho que el ordenador solo sabe ejecutar instrucciones muy sencillas. En nuestro ejemplo, solo hemos utilizado
tres instrucciones distintas:
una instruccin de suma de la forma
r;

una instruccin de divisin de la forma


r;

y una instruccin que indica que se ha llegado al final del programa:

Pocos programas interesantes podemos hacer con tan solo estas tres instrucciones! Naturalmente, en un cdigo de mquina hay instrucciones que permiten efectuar sumas, restas,
divisiones y otras muchas operaciones. Y hay, adems, instrucciones que permiten escoger qu
instruccin se ejecutar a continuacin, bien directamente, bien en funcin de si se cumple o
no determinada condicin (por ejemplo,
p).
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1.3.2.

Lenguaje ensamblador

En los primeros tiempos de la informtica los programas se introducan en el ordenador


directamente en cdigo de mquina, indicando uno por uno el valor de los bits de cada una
de las posiciones de memoria. Para ello se insertaban manualmente cables en un panel de
conectores: cada cable insertado en un conector representaba un uno y cada conector sin cable
representaba un cero. Como puedes imaginar, programar as un computador resultaba una tarea
ardua, extremadamente tediosa y propensa a la comisin de errores. El ms mnimo fallo conduca
a un programa incorrecto. Pronto se disearon notaciones que simplificaban la programacin:
cada instruccin de cdigo de mquina se representaba mediante un cdigo mnemotcnico, es
decir, una abreviatura fcilmente identificable con el propsito de la instruccin.
Por ejemplo, el programa desarrollado antes se podra representar como el siguiente texto:

En este lenguaje la palabra


representa la instruccin de sumar,
la de dividir y
representa la instruccin que indica que debe finalizar la ejecucin del programa. La almohadilla
( ) delante de un nmero indica que deseamos acceder al contenido de la posicin de memoria
cuya direccin es dicho nmero. Los caracteres que representan el programa se introducen en
la memoria del ordenador con la ayuda de un teclado y cada letra se almacena en una posicin
de memoria como una combinacin particular de unos y ceros (su cdigo ASCII, por ejemplo).
Pero cmo se puede ejecutar ese tipo de programa si la secuencia de unos y ceros que la
describe como texto no constituye un programa vlido en cdigo de mquina? Con la ayuda de
otro programa: el ensamblador. El ensamblador es un programa traductor que lee el contenido
de las direcciones de memoria en las que hemos almacenado cdigos mnemotcnicos y escribe
en otras posiciones de memoria sus instrucciones asociadas en cdigo de mquina.
El repertorio de cdigos mnemotcnicos traducible a cdigo de mquina y las reglas que
permiten combinarlos, expresar direcciones, codificar valores numricos, etc., recibe el nombre de
lenguaje ensamblador, y es otro lenguaje de programacin.

1.3.3.

Un programa diferente para cada ordenador?

Cada CPU tiene su propio juego de instrucciones y, en consecuencia, un cdigo de mquina


y uno o ms lenguajes ensambladores propios. Un programa escrito para una CPU de la marca
Intel no funcionar en una CPU diseada por otro fabricante, como Motorola3 . Incluso diferentes
versiones de una misma CPU tienen juegos de instrucciones que no son totalmente compatibles
entre s!: los modelos ms evolucionados de una familia de CPU pueden incorporar instrucciones
que no se encuentran en los ms antiguos4 .
Si queremos que un programa se ejecute en ms de un tipo de ordenador, habr que escribirlo de nuevo para cada CPU particular? Durante mucho tiempo se intent definir algn tipo
de lenguaje ensamblador universal, es decir, un lenguaje cuyos cdigos mnemotcnicos, sin
corresponderse con los del cdigo de mquina de ningn ordenador concreto, fuesen fcilmente
traducibles al cdigo de mquina de cualquier ordenador. Disponer de dicho lenguaje permitira
escribir los programas una sola vez y ejecutarlos en diferentes ordenadores tras efectuar las correspondientes traducciones a cada cdigo de mquina con diferentes programas ensambladores.
Si bien la idea es en principio interesante, presenta serios inconvenientes:
Un lenguaje ensamblador universal no puede tener en cuenta cmo se disearn ordenadores en un futuro y qu tipo de instrucciones soportarn, as que posiblemente quede
obsoleto en poco tiempo.

3 A menos que la CPU se haya diseado expresamente para reproducir el funcionamiento de la primera, como ocurre
con los procesadores de AMD, diseados con el objetivo de ejecutar el cdigo de mquina de los procesadores de Intel.
4 Por ejemplo, aadiendo instrucciones que faciliten la programacin de aplicaciones multimedia (como ocurre con los
Intel Pentium MMX y modelos posteriores) prcticamente impensables cuando se dise la primera CPU de la familia
(el Intel 8086).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Hola, mundo!

Nos gustara mostrarte el aspecto de los programas escritos en lenguajes ensambladores reales
con un par de ejemplos. Es una tradicin ilustrar los diferentes lenguajes de programacin con un
programa sencillo que se limita a mostrar por pantalla el mensaje Hello, World! (Hola, mundo!),
as que la seguiremos. He aqu ese programa escrito en los lenguajes ensambladores de dos CPU
distintas: a mano izquierda, el de los procesadores 80x86 de Intel (cuyos ltimos representantes por
el momento son la familia de procesadores i5 e i7) y, a mano derecha, el de los procesadores de la
familia Motorola 68000 (que es el procesador de los primeros ordenadores Apple Macintosh).

Como puedes ver, ambos programas presentan un aspecto muy diferente. Por otra parte, los dos son
bastante largos (entre 10 y 20 lneas) y de difcil comprensin, a menos que se cuente con conocimiento
preciso de lo que hace cada instruccin y las reglas sintcticas de cada lenguaje ensamblador.

Programar en lenguaje ensamblador (incluso en ese supuesto lenguaje ensamblador universal) es complicadsimo por los numerosos detalles que deben tenerse en cuenta.

Adems, puestos a disear un lenguaje de programacin general, por qu no utilizar un


lenguaje natural, es decir un lenguaje como el castellano o el ingls? Programar un computador
consistira, simplemente, en escribir (o pronunciar frente a un micrfono!) un texto en el que
indicsemos qu deseamos que haga el ordenador usando el mismo lenguaje con que nos comunicamos con otras personas. Un programa informtico podra encargarse de traducir nuestras
frases al cdigo de mquina, del mismo modo que un programa ensamblador traduce lenguaje
ensamblador a cdigo de mquina. Es una idea atractiva, pero que queda lejos de lo que sabemos
hacer por varias razones:

La complejidad intrnseca de las construcciones de los lenguajes naturales dificulta enormemente el anlisis sintctico de las frases, es decir, comprender su estructura y cmo se
relacionan entre s los diferentes elementos que las constituyen.

El anlisis semntico, es decir, la comprensin del significado de las frases, es an ms


complicado. Las ambigedades e imprecisiones del lenguaje natural hacen que sus frases
presenten, fcilmente, diversos significados, aun cuando las podamos analizar sintcticamente. (Cuntos significados tiene la frase Trabaja en un banco.?) Sin una buena
comprensin del significado no es posible efectuar una traduccin aceptable.

1.3.4.

Lenguajes de programacin de alto nivel

Hay una solucin intermedia: podemos disear lenguajes de programacin que, sin ser tan
potentes y expresivos como los lenguajes naturales, eliminen buena parte de la complejidad
propia de los lenguajes ensambladores y estn bien adaptados al tipo de problemas que podemos

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

resolver con los computadores: los denominados lenguajes de programacin de alto nivel. El
calificativo de alto nivel seala su independencia de un ordenador concreto. Por contraposicin,
los cdigos de mquina y los lenguajes ensambladores se denominan lenguajes de programacin
de bajo nivel.
He aqu el programa que calcula la media de tres nmeros en un lenguaje de alto nivel tpico
(Python):

Las tres primeras lneas definen los tres valores y la cuarta calcula la media. Como puedes ver,
resulta mucho ms legible que un programa en cdigo de mquina o en un lenguaje ensamblador.
Para cada lenguaje de alto nivel y para cada CPU se puede escribir un programa que se
encargue de traducir las instrucciones del lenguaje de alto nivel a instrucciones de cdigo de
mquina, con lo que se consigue la deseada independencia de los programas con respecto a
los diferentes sistemas computadores. Solo habr que escribir una versin del programa en un
lenguaje de programacin de alto nivel y la traduccin de ese programa al cdigo de mquina
de cada CPU se realizar automticamente.

1.3.5.

Compiladores e intrpretes

Hemos dicho que los lenguajes de alto nivel se traducen automticamente a cdigo de
mquina, s, pero has de saber que hay dos tipos diferentes de traductores dependiendo de su
modo de funcionamiento: compiladores e intrpretes.
Un compilador lee completamente un programa en un lenguaje de alto nivel y lo traduce
en su integridad a un programa de cdigo de mquina equivalente. El programa de cdigo de
mquina resultante se puede ejecutar cuantas veces se desee, sin necesidad de volver a traducir
el programa original.
Un intrprete acta de un modo distinto: lee un programa escrito en un lenguaje de alto nivel
instruccin a instruccin y, para cada una de ellas, efecta una traduccin a las instrucciones de
cdigo de mquina equivalentes y las ejecuta inmediatamente. No hay un proceso de traduccin
separado por completo del de ejecucin. Cada vez que ejecutamos el programa con un intrprete,
se repite el proceso de traduccin y ejecucin, ya que ambos son simultneos.
Compiladores e intrpretes. . . de idiomas

Puede resultarte de ayuda establecer una analoga entre compiladores e intrpretes de lenguajes
de programacin y traductores e intrpretes de idiomas.
Un compilador acta como un traductor que recibe un libro escrito en un idioma determinado
(lenguaje de alto nivel) y escribe un nuevo libro que, con la mayor fidelidad posible, contiene una
traduccin del texto original a otro idioma (cdigo de mquina). El proceso de traduccin (compilacin)
tiene lugar una sola vez y podemos leer el libro (ejecutar el programa) en el idioma destino (cdigo
de mquina) cuantas veces queramos.
Un intrprete de programas acta como su homnimo en el caso de los idiomas. Supn que
se imparte una conferencia en ingls en diferentes ciudades y un intrprete ofrece su traduccin
simultnea al castellano. Cada vez que la conferencia es pronunciada, el intrprete debe realizar
nuevamente la traduccin. Es ms, la traduccin se produce sobre la marcha, frase a frase, y no de un
tirn al final de la conferencia. Del mismo modo acta un intrprete de un lenguaje de programacin:
traduce cada vez que ejecutamos el programa y adems lo hace instruccin a instruccin.

Por regla general, los intrpretes ejecutarn los programas ms lentamente, pues al tiempo
de ejecucin del cdigo de mquina se suma el que consume la traduccin simultnea. Adems,
un compilador puede examinar el programa de alto nivel abarcando ms de una instruccin cada
vez, por lo que es capaz de producir mejores traducciones. Un programa interpretado suele ser
mucho ms lento que otro equivalente que haya sido compilado (tpicamente entre 2 y 100 veces
ms lento!).
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Si tan lento resulta interpretar un programa, por qu no se usan nicamente compiladores?


Es pronto para que entiendas las razones, pero, por regla general, los intrpretes permiten
una mayor flexibilidad que los compiladores y ciertos lenguajes de programacin de alto nivel
han sido diseados para explotar esa mayor flexibilidad. Otros lenguajes de programacin, por
contra, sacrifican la flexibilidad en aras de una mayor velocidad de ejecucin. Aunque nada
impide que compilemos o interpretemos cualquier lenguaje de programacin, ciertos lenguajes
se consideran apropiados para que la traduccin se lleve a cabo con un compilador y otros no. Es
ms apropiado hablar, pues, de lenguajes de programacin tpicamente interpretados y lenguajes
de programacin tpicamente compilados. Entre los primeros podemos citar Python, BASIC, Perl,
Tcl, Ruby, Bash, Java o Lisp. Entre los segundos, C, C , Pascal, C o Fortran.5
En el primer curso de los grados en Ingeniera Informtica y en Matemtica Computacional
de la Universitat Jaume I aprenderemos a programar usando dos lenguajes de programacin
distintos: uno interpretado, Python, y otro, Java, que puede ser interpretado o compilado a partir
de un lenguaje intermedio. Este volumen se dedica al estudio del lenguaje de programacin
Python.

1.3.6.

Python

Existen muchos otros lenguajes de programacin, por qu aprender Python? Python presenta
una serie de ventajas que lo hacen muy atractivo, tanto para su uso profesional como para el
aprendizaje de la programacin. Entre las ms interesantes desde el punto de vista didctico
tenemos:
Python es un lenguaje muy expresivo, es decir, los programas Python son muy compactos:
un programa Python suele ser bastante ms corto que su equivalente en lenguajes como
C. (Python llega a ser considerado por muchos un lenguaje de programacin de muy alto
nivel).
Python es muy legible. La sintaxis de Python es muy elegante y permite la escritura de
programas cuya lectura resulta ms fcil que si utilizramos otros lenguajes de programacin.

Python ofrece un entorno interactivo que facilita la realizacin de pruebas y ayuda a


despejar dudas acerca de ciertas caractersticas del lenguaje.

El entorno de ejecucin de Python detecta muchos de los errores de programacin que


escapan al control de los compiladores y proporciona informacin muy rica para detectarlos
y corregirlos.

Python puede usarse como lenguaje imperativo procedimental o como lenguaje orientado
a objetos.
Posee un rico juego de estructuras de datos que se pueden manipular de modo sencillo.

Estas caractersticas hacen que sea relativamente fcil traducir mtodos de clculo a programas
Python.
Los lenguajes de programacin no permanecen inmutables a lo largo del tiempo: evolucionan.
Python no es una excepcin. A partir de la experiencia con una versin del lenguaje y de
la influencia que ejercen otros lenguajes sobre los programadores, hay una presin constante
por hacer que el lenguaje ofrezca nuevas capacidades o simplifique el modo en el que se
expresan ciertos clculos. Python fue diseado inicialmente por Guido van Rossum a partir
de su experiencia colaborando con otros en el desarrollo de un lenguaje experimental: ABC. La
World Wide Web apareca al poco de crearse la primera versin de Python y ayudaba a poner
en contacto a miles de programadores en todo el mundo. La elegancia de Python, unida a la
aparicin de un nuevo medio de comunicacin entre especialistas, hicieron que un lenguaje que

5 Lo cierto es que la mayora de los lenguajes interpretados se traducen primero a un lenguaje intermedio que es el
realmente interpretado. Ocurre, por ejemplo, con Python y Java. C es an ms especial: los programas escritos en este
lenguaje se traducen a un lenguaje intermedio que, a su vez, se traduce a cdigo de mquina en cada ejecucin, pero
de una sola vez. Este modelo de compilacin en dos etapas tambin ha pasado a ser corriente para Java.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

no provena de la academia o la industria tuviera un xito inusitado. Hablamos de los aos 90


del pasado siglo, dcada en la que fue tomando fuerza el concepto de software libre.
Una activa comunidad de desarrolladores liderada por Guido van Rossum (quien sigue teniendo la ltima palabra en todas las decisiones) va mejorando el lenguaje progresivamente.
Cada nueva versin se marca con una serie de nmeros separados por puntos. Lee, si quieres,
el cuadro titulado Versiones para entender ms sobre la codificacin tradicional de versiones
de productos software.
Versiones

Los productos software evolucionan aadiendo funcionalidad o corrigiendo errores presentes en


una versin determinada. Se ha adoptado un convenio para referirse a cada una de las versiones de
un producto software: una serie de nmeros separados por puntos. Tpicamente se usan 2 nmeros
separados por un punto: el nmero principal (major version number) y el nmero secundario (minor
version number). La primera versin de un producto es la 1.0. Si se aade funcionalidad menor o
se corrigen errores menores, el autor del software ir produciendo las versiones 1.1, 1.2, 1.3, etc. del
producto (y que no acaba con la 1.9, pues puede seguir la 1.10, la 1.11, etc.). Se entiende que todas
esas versiones son compatibles hacia atrs, es decir, los datos que sirven para la versin 1.x son
utilizables en toda versin 1.y donde y > x. En ocasiones se sacan versiones que contienen cambios
tan pequeos que no merece avanzar ni siquiera el nmero secundario. As, a la versin 1.6 le puede
suceder la 1.6.1 y a esta la 1.6.2 para pasar luego a la 1.7. Cuando hay un cambio de funcionalidad
importante, se inicia una nueva serie de versiones que comienza en la 2.0. A la 2.0 le sigue la 2.1 y
as sucesivamente.
Pero no siempre las cosas son tan sencillas. El software que se produce en empresas suele
considerar aspectos relacionados con el mrketing y omitir o esconder la numeracin que hemos
presentado. El sistema operativo Microsoft Windows sigui el criterio que hemos descrito en un
principio. Hubo un Microsoft Windows 1.0, un 1.1, un 2.0, un 3.0 y un 3.1. Incluso un 3.11. Pero
la numeracin se rompi aparentemente con Microsoft Windows 95. Decimos aparentemente porque
internamente se mantuvo. Esa versin de Windows es la cuarta. La serie XP es la quinta. Microsoft
Windows Vista es la versin 6.0. Y Microsoft Windows 7 es la. . . 6.1!
Hemos hablado nicamente de las versiones que se lanzan al pblico. Durante el desarrollo hay
varias fases de pruebas antes de lanzar un producto. La primera versin que se hace pblica es la
versin alfa. As, un producto puede tener una versin 1.3 alfa y hacerla pblica para pedir a
potenciales colaboradores que ayuden a detectar errores. No es raro que se programe lanzar dos
versiones alfa. Por ejemplo 1.3 alfa 1 y 1.3 alfa 2, recogiendo la segunda correcciones a errores
detectados en la primera o incorporando alguna mejora de ltima hora. Cuando el software empieza
a considerarse robusto se pasa a las versiones beta, de las que tambin suele planificarse un par
de versiones. En las versiones beta solo se corrigen errores y no se aade nueva funcionalidad. Y
antes de salir al mercado, an se programa una versin casi definitiva: la versin RC (por Release
Candidate o candidato para lanzamiento). Nuestro hipottico producto conocera entonces una
versin 1.3 RC. Si la RC contuviera an numerosos fallos (lo que no sera buena seal), podra
publicarse una segunda RC, es decir, una versin 1.3 RC2. No hay obligacin de seguir este esquema
de numeracin, pero lo encontrars con frecuencia en muchos productos.
En el momento de escribir estas lneas, se ha publicado la versin de Python 3.4, precedida por
las versiones 3.4 alpha 1, 2, 3 y 4; 3.4 beta 1, 2 y 3; 3.4 RC 1, 2 y 3.

La primera versin de Python con un uso extendido es la 1.5. Una gran comunidad de
desarrolladores, liderada por el autor original, trabaja continuamente en la mejora del lenguaje.
Aproximadamente cada ao se hace pblica una nueva versin de Python. Tranquilo! No es que
con cada versin cambie radicalmente el lenguaje de programacin, sino que este se enriquece
manteniendo en lo posible la compatibilidad con los programas escritos para versiones anteriores.
Nosotros utilizaremos caractersticas de la versin 3.1 de Python, por lo que debers utilizar esa
versin o una superior.
Una ventaja fundamental de Python es la gratuidad de su intrprete. Puedes descargar el
intrprete de la pgina web
. El intrprete de Python tiene versiones
para prcticamente cualquier plataforma en uso: sistemas PC bajo Linux, sistemas PC bajo
Microsoft Windows, sistemas Macintosh de Apple, etc.
Para que te vayas haciendo a la idea de qu aspecto presenta un programa completo en
Python, te presentamos uno que calcula la media de tres nmeros que introduce por teclado el
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

usuario y muestra el resultado por pantalla:

Python 2.x y Python 3.x

Estamos en un momento especial en el desarrollo de Python: conviven dos ramas del lenguaje
que evolucionan simultneamente. Una rama, la que se conoce como 2.x, public hace varios meses la
versin 2.7.6 del lenguaje. La otra, conocida como 3.x, acaba de publicar la versin 3.4.0. El lenguaje
Python es bsicamente el mismo en las dos ramas, pero hay algunas diferencias importantes que hacen
que un programa escrito para la versin 2.7 no siempre funcione en la versin 3.4. No ocurre lo mismo
con los programas escritos para versiones distintas de la misma serie, es decir, un programa escrito
para la versin 2.4, por ejemplo, debera funcionar perfectamente con un intrprete de cualquier versin
posterior en la serie 2.x. Decimos que cada versin de la serie 2.x (o 3.x) presenta compatibilidad
hacia atrs dentro de la misma serie.
Por qu hay una rama 3.x incompatible con programas escritos para Python 2.x? A lo largo de
los aos se fueron detectando fallos o aspectos poco elegantes del diseo de Python, cuya correccin
o mejora supondra que los programas ya escritos dejaran de funcionar. Guido van Rossum hablaba
entonces de una versin de Python ideal en la que todos los problemas estaran resueltos: Python
3000. El nmero 3000 era una referencia jocosa tanto a la versin en la que todo estara resuelto
como al ao en el que se publicara esa versin. Un buen da decidi no esperar tanto y anunci que
Python creara un desarrollo en dos ramas: la serie 2.x y la 3.x. Durante un tiempo, los programadores
encontraran mejoras en el lenguaje que no introduciran incompatibilidades (la serie 2.x), pero se
animaba a que, en unos pocos aos, todos fueran adaptando sus programas a la versin 3.x. Pasado
un tiempo razonable, se cancelara el desarrollo en la serie 2.x y solo evolucionara la 3.x. Un plan
sensato para no estancar el lenguaje y no fastidiar a todos los programadores que haban apostado
por Python hace aos.

En la ltima dcada Python ha experimentado un importantsimo aumento del nmero de


programadores y empresas que lo utilizan. Google, por ejemplo, usa Python como uno de sus
principales lenguajes de desarrollo (otros dos son Java y C ). Guido van Rossum, inventor de
Python, trabaja en Google. Tambin YouTube usa Python en sus sistemas de explotacin. E
Industrial Light & Magic (la empresa de efectos especiales de George Lucas) y Pixar recurren
a Python en sus sistemas de produccin cinematogrfica. Y si alguna vez has usado BitTorrent,
el popular sistema P2P, has de saber que est escrito en Python. La relacin de empresas e
instituciones que usa Python es inacabable: Intel, Hewlett-Packard, NASA, JPMorgan Chase,
etc. Aqu tienes unas citas que encabezaron durante algn tiempo la web oficial de Python
(
):
Python ha sido parte importante de Google desde el principio, y lo sigue siendo
a medida que el sistema crece y evoluciona. Hoy da, docenas de ingenieros de
Google usan Python y seguimos buscando gente diestra en este lenguaje.
Peter Norvig, director de calidad de bsquedas de Google Inc.

Python juega un papel clave en nuestra cadena de produccin. Sin l, un proyecto


de la envergadura de Star Wars: Episodio II hubiera sido muy difcil de sacar
adelante. Visualizacin de multitudes, proceso de lotes, composicin de escenas. . .
Python es lo que lo une todo.
Tommy Brunette, director tcnico senior de Industrial Light & Magic.

Python est en todas partes de Industrial Light & Magic. Se usa para extender
la capacidad de nuestras aplicaciones y para proporcionar la cola que las une. Cada
imagen generada por computador que creamos incluye a Python en algn punto del
proceso.
Philip Peterson, ingeniero principal de I+D de Industrial Light & Magic.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1.3.7.

Java

El lenguaje de programacin Java es uno de los ms utilizados en el mundo profesional.


Se dise por tcnicos de Sun Microsystems a mediados de los aos 90 como un lenguaje
y entorno de programacin cuyos programas seran ejecutables en todo tipo de dispositivos:
telfonos mviles, televisores, microondas, etc. Al presentarse en pblico, Java permita crear
pequeos programas ejecutables en navegadores web: los denominados applets. En ese momento,
la posibilidad de extender la experiencia de la navegacin con aplicaciones interactivas era
revolucionaria y dio un gran impulso al lenguaje. Pero finalmente Java se impuso en el mundo
de las aplicaciones web del lado del servidor. Las aplicaciones web ofrecen servicios accesibles
con el mismo protocolo de comunicacin que usan los navegadores.
Finalmente no (solo) es el lenguaje en s lo que hace productivo el trabajo de los desarrolladores: la coleccin de utilidades y bibliotecas que lo acompaan es fundamental. Java cuenta
con un entorno de desarrollo muy rico y un gran conjunto de libreras de cdigo, es decir, colecciones de funciones ya escritas que el programador usa para no tener que reinventar la rueda
constantemente.
No obstante, programar con Java requiere un mayor esfuerzo que hacerlo con Python. Los
programas Java son ms extensos y requieren de una gran atencin a muchos detalles por parte
del programador.
La torre de Babel

Hemos dicho que los lenguajes de programacin de alto nivel pretendan, entre otros objetivos,
paliar el problema de que cada ordenador utilice su propio cdigo de mquina. Puede que, en consecuencia, ests sorprendido por el nmero de lenguajes de programacin citados. Pues los que hemos
citado son unos pocos de los ms utilizados: hay centenares! Por qu tantos?
El primer lenguaje de programacin de alto nivel fue Fortran, que se dise en los primeros
aos 50 (y an se utiliza hoy da, aunque en versiones evolucionadas). Fortran se dise con el
propsito de traducir frmulas matemticas a cdigo de mquina (de hecho, su nombre proviene de
FORmula TRANslator, es decir, traductor de frmulas). Poco despus se disearon otros lenguajes
de programacin con propsitos especficos: Cobol (Common Business Oriented Language), Lisp (List
Processing language), etc. Cada uno de estos lenguajes haca fcil la escritura de programas para
solucionar problemas de mbitos particulares: Cobol para problemas de gestin empresarial, Lisp
para ciertos problemas de Inteligencia Artificial, etc. Hubo tambin esfuerzos para disear lenguajes
de propsito general, es decir, aplicables a cualquier dominio, como Algol 60 (Algorithmic Language).
En la dcada de los 60 hicieron su aparicin nuevos lenguajes de programacin (Algol 68, Pascal,
Simula 67, Snobol 4, etc.), pero quiz lo ms notable de esta dcada fue que se sentaron las bases
tericas del diseo de compiladores e intrpretes. Cuando la tecnologa para el diseo de estas
herramientas se hizo accesible a ms y ms programadores hubo un autntico estallido en el nmero
de lenguajes de programacin. Ya en 1969 se haban diseado unos 120 lenguajes de programacin y
se haban implementado compiladores o intrpretes para cada uno de ellos.
La existencia de tantsimos lenguajes de programacin cre una situacin similar a la de la torre
de Babel: cada laboratorio o departamento informtico usaba un lenguaje de programacin y no haba
forma de intercambiar programas.
Con los aos se ha ido produciendo una seleccin de aquellos lenguajes de programacin ms
adecuados para cada tipo de tarea y se han diseado muchos otros que sintetizan lo aprendido de
lenguajes anteriores. Los ms utilizados hoy da son Java, C, C , Python, Perl y PHP.
Si tienes curiosidad, puedes ver ejemplos del programa Hello, world! en ms de 100 lenguajes de programacin diferentes visitando la pgina

1.4.

Ms all de los programas: algoritmos

Dos programas que resuelven el mismo problema expresados en el mismo o en diferentes


lenguajes de programacin pero que siguen, en lo fundamental, el mismo procedimiento, son dos
implementaciones del mismo algoritmo. Un algoritmo es, sencillamente, una secuencia de pasos
orientada a la consecucin de un objetivo.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Cuando diseamos un algoritmo podemos expresarlo en uno cualquiera de los numerosos


lenguajes de programacin de propsito general existentes. Sin embargo, ello resulta poco adecuado:
no todos los programadores conocen todos los lenguajes y no hay consenso acerca de cul
es el ms adecuado para expresar las soluciones a los diferentes problemas,
cualquiera de los lenguajes de programacin presenta particularidades que pueden interferir en una expresin clara y concisa de la solucin a un problema.

Podemos expresar los algoritmos en lenguaje natural, pues el objetivo es comunicar un


procedimiento resolutivo a otras personas y, eventualmente, traducirlos a algn lenguaje de
programacin. Si, por ejemplo, deseamos calcular la media de tres nmeros ledos de teclado
podemos seguir este algoritmo:
1) solicitar el valor del primer nmero,

2) solicitar el valor del segundo nmero,


3) solicitar el valor del tercer nmero,

4) sumar los tres nmeros y dividir el resultado por 3,


5) mostrar el resultado.

Como puedes ver, esta secuencia de operaciones define exactamente el proceso que nos permite
efectuar el clculo propuesto y que ya hemos implementado como un programa en Python.
Los algoritmos son independientes del lenguaje de programacin. Describen un procedimiento
que puede ser implementado en cualquier lenguaje de programacin de propsito general o,
incluso, que puedes ejecutar a mano con lpiz, papel y, quiz, la ayuda de una calculadora.
Ojo! No es cierto que cualquier procedimiento descrito paso a paso pueda considerarse un
algoritmo. Un algoritmo debe satisfacer ciertas condiciones. Una analoga con recetas de cocina
(procedimientos para preparar platos) te ayudar a entender dichas restricciones.
Estudia esta primera receta:
1) poner aceite en una sartn,
2) encender el fuego,
3) calentar el aceite,
4) coger un huevo,

5) romper la cscara,

6) verter el contenido del huevo en la sartn,


7) aderezar con sal,

8) esperar a que tenga buen aspecto.

En principio ya est: con la receta, sus ingredientes y los tiles necesarios somos capaces
de cocinar un plato. Bueno, no del todo cierto, pues hay unas cuantas cuestiones que no quedan
del todo claras en nuestra receta:
Qu tipo de huevo utilizamos?: un huevo de gallina?, un huevo de rana?
Cunta sal utilizamos?: una pizca?, un kilo?

Cunto aceite hemos de verter en la sartn?: un centmetro cbico?, un litro?

Cul es el resultado del proceso?, la sartn con el huevo cocinado y el aceite?


Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

En una receta de cocina hemos de dejar bien claro con qu ingredientes contamos y cul es el
resultado final. En un algoritmo hemos de precisar cules son los datos del problema (datos de
entrada) y qu resultado vamos a producir (datos de salida).
Esta nueva receta corrige esos fallos:
Ingredientes: 10 cc. de aceite de oliva, una gallina y una pizca de sal.
Mtodo:

1) esperar a que la gallina ponga un huevo,


2) poner aceite en una sartn,
3) encender el fuego,
4) calentar el aceite,
5) coger el huevo,

6) romper la cscara,

7) verter el contenido del huevo en la sartn,


8) aderezar con sal,

9) esperar a que tenga buen aspecto.

Presentacin: depositar el huevo frito, sin aceite, en un plato.

Pero la receta an no est bien del todo. Hay ciertas indefiniciones en la receta:

1) Cun caliente ha de estar el aceite en el momento de verter el huevo?, humeando?, ardiendo?


2) Cunto hay que esperar?, un segundo?, hasta que el huevo est ennegrecido?

3) Y an peor, estamos seguros de que la gallina pondr un huevo? Podra ocurrir que la
gallina no pusiera huevo alguno.

Para que la receta est completa, deberamos especificar con absoluta precisin cada uno de
los pasos que conducen a la realizacin del objetivo y, adems, cada uno de ellos debera ser
realizable en tiempo finito.
No basta con decir ms o menos cmo alcanzar el objetivo: hay que decir exactamente cmo
se debe ejecutar cada paso y, adems, cada paso debe ser realizable en tiempo finito. Esta
nueva receta corrige algunos de los problemas de la anterior, pero presenta otros de distinta
naturaleza:
Ingredientes: 10 cc. de aceite de oliva, un huevo de gallina y una pizca de sal.
Mtodo:

1) poner aceite en una sartn,

2) encender el fuego a medio gas,

3) calentar el aceite hasta que humee ligeramente,


4) coger un huevo,

5) romper la cscara con el poder de la mente, sin tocar el huevo,


6) verter el contenido del huevo en la sartn,
7) aderezar con sal,

8) esperar a que tenga buen aspecto.

Presentacin: depositar el huevo frito, sin aceite, en un plato.

El quinto paso no es factible. Para romper un huevo has de utilizar algo ms que el poder de la
mente. En todo algoritmo debes utilizar nicamente instrucciones que pueden llevarse a cabo.
He aqu una receta en la que todos los pasos son realizables:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ingredientes: 10 cc. de aceite de oliva, un huevo de gallina y una pizca de sal.


Mtodo:

1) poner aceite en una sartn,

2) sintonizar una emisora musical en la radio,


3) encender el fuego a medio gas,
4) echar una partida al solitario,

5) calentar el aceite hasta que humee ligeramente,


6) coger un huevo,

7) romper la cscara,

8) verter el contenido del huevo en la sartn,


9) aderezar con sal,

10) esperar a que tenga buen aspecto.

Presentacin: depositar el huevo frito, sin aceite, en un plato.

En esta nueva receta hay acciones que, aunque expresadas con suficiente precisin y siendo
realizables, no hacen nada til para alcanzar nuestro objetivo (sintonizar la radio y jugar a las
cartas). En un algoritmo, cada paso dado debe conducir y acercarnos ms a la consecucin del
objetivo.
Hay una consideracin adicional que hemos de hacer, aunque en principio parezca una
obviedad: todo algoritmo bien construido debe finalizar tras la ejecucin de un nmero finito de
pasos.
Aunque todos los pasos sean de duracin finita, una secuencia de instrucciones puede requerir
tiempo infinito. Piensa en este mtodo para hacerse millonario:
1) comprar un nmero de lotera vlido para el prximo sorteo,
2) esperar al da de sorteo,

3) cotejar el nmero ganador con el nuestro,

4) si son diferentes, volver al paso 1; en caso contrario, somos millonarios.

Como ves, cada uno de los pasos del mtodo requiere una cantidad finita de tiempo, pero no hay
ninguna garanta de alcanzar el objetivo propuesto.
En adelante, no nos interesarn ms las recetas de cocina ni los procedimientos para enriquecerse sin esfuerzo (al menos no como objeto de estudio de la asignatura!). Los algoritmos en
los que estaremos interesados son aquellos que describen procedimientos de clculo ejecutables
en un ordenador. Ello limitar el mbito de nuestro estudio a la manipulacin y realizacin de
clculos sobre datos (numricos, de texto, etc.).
Un algoritmo debe poseer las siguientes caractersticas:
1) Ha de tener cero o ms datos de entrada.

2) Debe proporcionar uno o ms datos de salida como resultado.

3) Cada paso del algoritmo ha de estar definido con exactitud, sin la menor ambigedad.

4) Ha de ser finito, es decir, debe finalizar tras la ejecucin de un nmero finito de pasos, cada
uno de los cuales ha de ser ejecutable en tiempo finito.

5) Debe ser efectivo, es decir, cada uno de sus pasos ha de poder ejecutarse en tiempo finito con
unos recursos determinados (en nuestro caso, con los que proporciona un sistema computador).
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Abu Jafar Mohammed ibn Ms Al-Khowrizm y Euclides

La palabra algoritmo tiene origen en el nombre de un matemtico persa del siglo IX: Abu Jafar
Mohammed ibn Ms Al-Khowrizm (que significa Mohammed, padre de Jafar, hijo de Moiss,
nacido en Khowrizm). Al-Khowrizm escribi tratados de aritmtica y lgebra. Gracias a los textos
de Al-Khowrizm se introdujo el sistema de numeracin hind en el mundo rabe y, ms tarde, en
Occidente.
En el siglo XIII se publicaron los libros Carmen de Algorismo (un tratado de aritmtica en verso!)
y Algorismus Vulgaris, basados en parte en la Aritmtica de Al-Khowrizm. Al-Khowrizm escribi
tambin el libro Kitab al jabr wal-muqabala (Reglas de restauracin y reduccin), que dio origen
a una palabra que ya conoces: lgebra.
Abelardo de Bath, uno de los primeros traductores al latn de Al-Khowrizm, empez un texto
con Dixit Algorismi. . . (Dijo Algorismo. . . ), popularizando as el trmino algorismo, que pas a
significar realizacin de clculos con numerales indoarbigos. En la Edad Media los abaquistas
calculaban con baco y los algorismistas con algorismos.
En cualquier caso, el concepto de algoritmo es muy anterior a Al-Khowrizm. En el siglo III a.C.,
Euclides propuso en su tratado Elementos un mtodo sistemtico para el clculo del Mximo Comn
Divisor (MCD) de dos nmeros. El mtodo, tal cual fue propuesto por Euclides, dice as: Dados dos
nmeros naturales, a y b, comprobar si ambos son iguales. Si es as, a es el MCD. Si no, si a es
mayor que b, restar a a el valor de b; pero si a es menor que b, restar a b el valor de a. Repetir
el proceso con los nuevos valores de a y b. Este mtodo se conoce como algoritmo de Euclides,
aunque es frecuente encontrar, bajo ese mismo nombre, un procedimiento alternativo y ms eficiente:
Dados dos nmeros naturales, a y b, comprobar si b es cero. Si es as, a es el MCD. Si no, calcular
c, el resto de dividir a entre b. Sustituir a por b y b por c y repetir el proceso.

Adems, nos interesa que los algoritmos sean eficientes, esto es, que alcancen su objetivo lo ms
rpidamente posible y con el menor consumo de recursos.

9
Disea un algoritmo para calcular el rea de un crculo dado su radio. Recuerda que
el rea de un crculo es veces el cuadrado del radio.
No hay una nica solucin. Diferentes personas ofrecern algoritmos distintos en funcin
del orden de las operaciones y del nivel de detalle de cada una. Alguien podra proponer este
algoritmo breve:
1) Devolver el producto de por el radio por el radio.

Otro podra alterar el orden de las operaciones:

1) Devolver el producto de radio por por el radio.


Y otro podra trabajar con pasos ms finos:

1) Calcular radio por el radio y denominar cuadrado al resultado.


2) Devolver el producto de pi por el valor de cuadrado.

10
sin IVA.

Disea un algoritmo que calcule el IVA (21 %) de un producto dado su precio de venta

11
Podemos llamar algoritmo a un procedimiento que escriba en una cinta de papel
todos los nmeros decimales de ?

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Captulo 2

Una calculadora avanzada

Sabes sumar? le pregunt la Reina Blanca. Cunto es uno ms uno ms


uno ms uno ms uno ms uno ms uno ms uno ms uno ms uno ms uno?
No lo s dijo Alicia. Perd la cuenta.
No sabe hacer una adicin le interrumpi la Reina Roja.
Alicia en el pas de las maravillas, Lewis Carroll

El objetivo de este captulo es que te familiarices con el entorno interactivo de Python, que
aprendas a construir expresiones aritmticas almacenando los resultados en variables mediante
asignaciones y que conozcas los tipos de datos bsicos del lenguaje de programacin Python.

2.1.

Sesiones interactivas

Cuando programamos utilizamos un conjunto de herramientas al que denominamos entorno


de programacin. Entre estas herramientas tenemos editores de texto (que nos permiten escribir
programas), compiladores o intrpretes (que traducen los programas a cdigo de mquina), depuradores (que ayudan a detectar errores), analizadores de tiempo de ejecucin (para estudiar la
eficiencia de los programas), herramientas para la ejecucin de pruebas unitarias (para asegurarnos de que no introducimos nuevos errores al ir desarrollando), analizadores de cobertura (para
asegurarnos de que todo el cdigo ha sido puesto a prueba), generadores de documentacin
(que generan documentacin en formatos como HTML a partir de comentarios en los programas), analizadores estticos (que detectan patrones tpicos en cdigo errneo y nos advierten de
problemas potenciales), sistemas de control de versiones (que permiten que varios programadores colaboren en un mismo programa, recuperar cualquier versin del programa, crear ramas de
desarrollo en paralelo. . . ), etc.
Los lenguajes interpretados suelen ofrecer una herramienta de ejecucin interactiva. Con ella
es posible dar rdenes directamente al intrprete y obtener una respuesta inmediata para cada
una de ellas. Es decir, no es necesario escribir un programa completo para empezar a obtener
resultados de ejecucin, sino que podemos dialogar con el intrprete de nuestro lenguaje de
programacin: le pedimos que ejecute una orden y nos responde con su resultado. El entorno
interactivo es de gran ayuda para experimentar con fragmentos de programa antes de incluirlos
en una versin definitiva.
En esta seccin veremos cmo realizar sesiones de trabajo interactivo con Python1 . Arrancaremos el intrprete interactivo de modo distinto segn el sistema operativo con el que estemos
trabajando:
Si estamos trabajando en un sistema Unix (como cualquiera de las variantes de Linux o
Mac OS X), tendremos que iniciar primero un intrprete de rdenes en un terminal. Busca
en los mens o barra de aplicaciones algn icono denominado terminal o bash. En la
ventana que se abrir al iniciar el terminal, escribe
y pulsa retorno de carro. Si

1 Abusando del lenguaje, llamaremos indistintamente Python al entorno de programacin, al intrprete del lenguaje
y al propio lenguaje de programacin.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

la versin de Python que se ejecuta no es la 3.1 (o superior), sal del intrprete escribiendo
y pulsando el retorno de carro para, a continuacin, escribir
y pulsar
nuevamente retorno de carro.
En Microsoft Windows puedes hacer una de dos cosas:

ir al men de aplicaciones y seleccionar el icono


carpeta
del men

en la

pulsar las tecla Windows y R simultneamente para que aparezca un cuadro de


; escribir en la caja de texto
y pulsar el botn
dilogo con ttulo
; en la ventana que aparece escribe entonces
y pulsa el retorno de
carro.

El sistema nos responder dando un mensaje informativo sobre la versin de Python que estamos
utilizando (y cundo fue compilada, con qu compilador, etc.) y, a continuacin, mostrar el prompt.
El resultado ser parecido a esto:

El prompt es la serie de caracteres


que aparece en la ltima lnea. El prompt indica
que el intrprete de Python espera que nosotros introduzcamos una orden utilizando el teclado.
Escribamos una expresin aritmtica, por ejemplo 2 2, y pulsemos la tecla de retorno de
carro. Cuando mostremos sesiones interactivas destacaremos el texto que teclea el usuario con
texto de color azul y representaremos con el smbolo
la pulsacin de la tecla de retorno
de carro. Python evala la expresin (es decir, obtiene su resultado) y responde mostrando el
resultado por pantalla.

La ltima lnea es, nuevamente, el prompt: Python acab de ejecutar la ltima orden (evaluar
una expresin y mostrar el resultado) y nos pide que introduzcamos una nueva orden.
Si deseamos acabar la sesin interactiva y salir del intrprete Python, debemos introducir
una marca de final de fichero, que en Unix se indica pulsando la tecla de control y, sin soltarla,
tambin la tecla . (De ahora en adelante representaremos una combinacin de teclas como la
).
descrita as:
Final de fichero

La marca de final de fichero indica que un fichero ha terminado. Pero nosotros no trabajamos
con un fichero, sino con el teclado! En realidad, el ordenador considera al teclado como un fichero.
Cuando deseamos cerrar el teclado para una aplicacin, enviamos una marca de final de fichero
desde el teclado. En Unix, la marca de final de fichero se enva pulsando la tecla de control y la tecla
d simultneamente, lo que indicamos con
; en Microsoft Windows, el final de fichero se indica
con
.
Existe otro modo de finalizar la sesin; escribe
en el intrprete y la sesin se cerrar. En
ingls, quit significa abandonar.

2.1.1.

Los operadores aritmticos

Las operaciones de suma y resta, por ejemplo, se denotan con los smbolos u operadores
y , respectivamente, y operan sobre dos valores numricos (los operandos). Probemos algunas
expresiones formadas con estos dos operadores:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Observa que puedes introducir varias operaciones en una misma lnea o expresin. El orden
en que se efectan las operaciones es (en principio) de izquierda a derecha. Por ejemplo, la
2
3 equivale matemticamente a ((1 2) + 3); por ello decimos que la suma y
expresin 1
la resta son operadores asociativos por la izquierda.
Podemos representar grficamente el orden de aplicacin de las operaciones utilizando rboles sintcticos. Un rbol sintctico es una representacin grfica en la que disponemos los
operadores y los operandos como nodos y en los que cada operador est conectado a sus ope2
3 es este:
randos. El rbol sintctico de la expresin 1

El nodo superior de un rbol recibe el nombre de nodo raz. Los nodos etiquetados con
operadores (representados con crculos) se denominan nodos interiores. Los nodos interiores tienen uno o ms nodos hijo o descendientes (de los que ellos son sus respectivos nodos padre
o ascendientes). Dichos nodos son nodos raz de otros (sub)rboles sintcticos (la definicin
de rbol sintctico es auto-referencial!). Los valores resultantes de evaluar las expresiones asociadas a dichos (sub)rboles constituyen los operandos de la operacin que representa el nodo
interior. Los nodos sin descendientes se denominan nodos terminales u hojas (representados con
cuadrados) y corresponden a valores numricos.
La evaluacin de cada operacin individual en el rbol sintctico fluye de las hojas hacia
2, que
la raz (el nodo superior); es decir, en primer lugar se evala la subexpresin 1
corresponde al subrbol ms profundo. El resultado de la evaluacin es 1:
1

A continuacin se evala la subexpresin que suma el resultado de evaluar 1


1

2 al valor 3:

As se obtiene el resultado final: el valor 2.


Si deseamos calcular (1 (2 + 3)) podemos hacerlo aadiendo parntesis a la expresin
aritmtica:
El rbol sintctico de esta nueva expresin es
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

En este nuevo rbol, la primera subexpresin evaluada es la que corresponde al subrbol


derecho:
4

Observa que en el rbol sintctico no aparecen los parntesis de la expresin. El rbol


sintctico ya indica el orden en que se procesan las diferentes operaciones y no necesita parntesis. La expresin Python, sin embargo, necesita los parntesis para indicar ese mismo orden
de evaluacin.
12
Qu expresiones Python permiten, utilizando el menor nmero posible de parntesis,
efectuar en el mismo orden los clculos representados con estos rboles sintcticos?

13
cas:
a) 1

b) 1
c) 1

2
2

Dibuja los rboles sintcticos correspondientes a las siguientes expresiones aritmti-

3
3

4
4

Los operadores de suma y resta son binarios, es decir, operan sobre dos operandos. El mismo
smbolo que se usa para la resta se usa tambin para un operador unario, es decir, un operador
que acta sobre un nico operando: el de cambio de signo, que devuelve el valor de su operando
cambiado de signo. He aqu algunos ejemplos:

He aqu los rboles sintcticos correspondientes a las tres expresiones del ejemplo:
3

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Espacios en blanco

Parece que se puede hacer un uso bastante liberal de los espacios en blanco en una expresin.

Es as. Has de respetar, no obstante, un par de sencillas reglas. Por una parte no puedes poner
espacios en medio de un nmero:

Los espacios en blanco entre el 2 y el 0 hacen que Python no lea el nmero 20, sino el nmero 2
seguido del nmero 0 (lo cual es un error, pues no hay operacin alguna entre ambos nmeros).
Por otra parte, no puedes poner espacios al principio de la expresin:

Los espacios en blanco entre el prompt y el 10 provocan un error. An es pronto para que conozcas
la razn.

Existe otro operador unario que se representa con el smbolo : el operador identidad. El
operador identidad no hace nada til: proporciona como resultado el mismo nmero que se le
pasa.
El operador identidad solo sirve para, en ocasiones, poner nfasis en que un nmero es
positivo. (El ordenador considera tan positivo el nmero 3 como el resultado de evaluar 3).
Los operadores de multiplicacin y divisin son, respectivamente, y :

Detengmonos brevemente a hacer una consideracin sobre el operador de divisin. Fjate


en que Python, al dividir 3 entre 2, ha proporcionado como respuesta el valor 1.5. Ese punto
que separa el 1 del 5 es lo que en espaol solemos denotar con una coma2 y que separa la
parte entera de un nmero de su parte decimal. El operador de divisin siempre proporciona
un nmero con parte decimal, aunque esta sea nula; es lo que ocurre al dividir, por ejemplo,
4 entre 2 con el operador : el resultado es 2.0. Hay otro operador de divisin que no tiene
2 El punto tambin se acepta en espaol, aunque se prefiere usar la coma. Python representa los nmeros siguiendo
el convenio anglosajn.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

ese efecto: es el operador de divisin entera


(sin espacio alguno entre las barras). Con
siempre obtienes un nmero entero como resultado de la divisin de dos enteros:

Observa que los operadores de multiplicacin y divisin (convencional y entera) tambin son
4
2 equivale a ((3 4)/2), es decir, tiene el
asociativos por la izquierda: la expresin 3
siguiente rbol sintctico:

y la expresin 12

2 equivale a ((12/3) 2), o sea, su rbol sintctico es:

12

Sigamos estudiando el orden de evaluacin cuando una expresin contiene diferentes operadores. Qu pasa si combinamos en una misma expresin operadores de suma o resta con
operadores de multiplicacin o divisin? Fjate en que la regla de aplicacin de operadores de
izquierda a derecha no siempre se observa:
En la segunda expresin, primero se ha efectuado el producto 4
5 y el resultado se ha
sumado al valor 2. Ocurre que los operadores de multiplicacin y divisin son prioritarios frente a
los de suma y resta. Decimos que la multiplicacin y la divisin tienen mayor nivel de precedencia
o prioridad que la suma y la resta.
El rbol sintctico de 2
4
5 es:

y el de 2

5 es:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

5
Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Pero atencin!, el cambio de signo tiene mayor prioridad que la multiplicacin y la divisin:
Los rboles sintcticos correspondientes a estas dos expresiones son, respectivamente:
2

Si los operadores siguen unas reglas de precedencia que determinan su orden de aplicacin,
qu hacer cuando deseamos un orden de aplicacin distinto? Usar parntesis, como hacemos
con la notacin matemtica convencional.
4
5 , por ejemplo, presenta este rbol sintctico:
La expresin 2
2

Existen ms operadores en Python. Tenemos, por ejemplo, el operador mdulo, que se denota
con el smbolo de porcentaje (aunque nada tiene que ver con el clculo de porcentajes). El
operador mdulo devuelve el resto de la divisin entera entre dos operandos.
El operador tambin es asociativo por la izquierda y su prioridad es la misma que la de
la multiplicacin o la divisin.
El ltimo operador que vamos a estudiar es la exponenciacin, que se denota con dos asteriscos juntos, no separados por ningn espacio en blanco: .
Lo que en notacin matemtica convencional expresamos como 23 se expresa en Python con
3.
2
Pero ojo!, la exponenciacin es asociativa por la derecha. La expresin 2
2
a 2 = 29 = 512, y no a (23 ) = 82 = 64, o sea, su rbol sintctico es:
(32 )

2 equivale

Por otra parte, la exponenciacin tiene mayor precedencia que cualquiera de los otros operadores presentados.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

He aqu varias expresiones evaluadas con Python y sus correspondientes rboles sintcticos.
Estdialos con atencin:

2
3

2
3

La tabla 2.1 resume las caractersticas de los operadores Python que ya conocemos: su aridad
(nmero de operandos), asociatividad y precedencia.

14
Qu resultados se obtendrn al evaluar las siguientes expresiones Python? Dibuja
el rbol sintctico de cada una de ellas, calcula a mano el valor resultante de cada expresin y
comprueba, con la ayuda del ordenador, si tu resultado es correcto.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Operacin

Operador

Aridad

Asociatividad

Precedencia

Exponenciacin
Binario Por la derecha
1
................................................................
Unario
2
Identidad
Unario
2
Cambio de signo
................................................................
Binario Por la izquierda
3
Multiplicacin
Binario Por la izquierda
3
Divisin
Binario Por la izquierda
3
Divisin entera
Mdulo (o resto)
Binario Por la izquierda
3
................................................................
Binario Por la izquierda
4
Suma
Binario Por la izquierda
4
Resta

Tabla 2.1: Operadores para expresiones aritmticas. El nivel de precedencia 1 es el de mayor


prioridad y el 4 el de menor.
a) 2

b) 2
c)

d)

g)

e)
f)

h)

3
3

1
1

3
3

6
6

2
2

15
Traduce las siguientes expresiones matemticas a Python y evalalas. Trata de utilizar
el menor nmero posible de parntesis.
a) 2 + (3 (6/2))

b)

4+6
2+3

c) (4/2)5

d) (4/2)4+2
e) (3)2

f) (32 )

2.1.2.

Errores de tecleo y excepciones

Cuando introducimos una expresin y damos la orden de evaluarla, es posible que nos
equivoquemos. Si hemos formado incorrectamente una expresin, Python nos lo indicar con un
mensaje de error. El mensaje de error proporciona informacin acerca del tipo de error cometido
y del lugar en el que este ha sido detectado. Aqu tienes una expresin errnea y el mensaje de
error correspondiente:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

En este ejemplo hemos cerrado un parntesis cuando no haba otro abierto previamente, lo
)y
cual es incorrecto. Python nos indica que ha detectado un error de sintaxis (
apunta con una punta de flecha (el carcter ) al lugar en el que se encuentra. (El texto
indica que el error se ha producido al leer de teclado, esto es, de la
es una abreviatura del ingls standard input, que se traduce por
entrada estndar
entrada estndar).
En Python los errores se denominan excepciones. Cuando Python es incapaz de analizar
una expresin, produce una excepcin. Cuando el intrprete interactivo detecta la excepcin, nos
muestra por pantalla un mensaje de error.
Veamos algunos otros errores y los mensajes que produce Python.

El ltimo error es de naturaleza distinta a los anteriores (no hay un carcter apuntando
), cuando los
a lugar alguno): se trata de un error de divisin por cero (
). La cantidad que resulta de dividir por cero no
otros eran errores sintcticos (
0.
est definida y Python es incapaz de calcular un valor como resultado de la expresin 1
No es un error sintctico porque la expresin est sintcticamente bien formada: el operador de
divisin tiene dos operandos, como toca.
Edicin avanzada en el entorno interactivo

Cuando estemos escribiendo una expresin puede que cometamos errores y los detectemos antes
de solicitar su evaluacin. An estaremos a tiempo de corregirlos. La tecla de borrado, por ejemplo,
elimina el carcter que se encuentra a la izquierda del cursor. Puedes desplazar el cursor a cualquier
punto de la lnea que ests editando utilizando las teclas de desplazamiento del cursor a izquierda y
a derecha. El texto que teclees se insertar siempre justo a la izquierda del cursor.
Hasta el momento hemos tenido que teclear desde cero cada expresin evaluada, aun cuando muchas se parecan bastante entre s. Podemos teclear menos si aprendemos a utilizar algunas funciones
de edicin avanzadas.
Lo primero que hemos de saber es que el intrprete interactivo de Python memoriza cada una de
las expresiones evaluadas en una sesin interactiva por si deseamos recuperarlas ms tarde. La lista
de expresiones que hemos evaluado constituye la historia de la sesin interactiva. Puedes navegar
por la historia utilizando las teclas de desplazamiento del cursor hacia arriba y hacia abajo. Cada vez
que pulses la tecla de desplazamiento hacia arriba recuperars una expresin ms antigua. La tecla
de desplazamiento hacia abajo permite recuperar expresiones ms recientes. La expresin recuperada
aparecer ante el prompt y podrs modificarla a tu antojo.

2.2.

Tipos de datos

Ya hemos visto que hay dos operadores de divisin. Uno es el convencional, que siempre
produce un nmero con decimales:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Y otro es el operador de divisin entera, que siempre produce un nmero sin decimales
cuando sus operandos son enteros:
Fjate en la diferencia entre el resultado de 4
2y4
2. No es lo mismo 2.0 que 2?
Pues no exactamente. El nmero 2 es un nmero de tipo entero y el nmero 2.0 lo es de tipo
flotante (o, mejor dicho, tipo de coma flotante). Cada valor en Python es una instancia de un tipo
de dato y de momento hemos visto datos de dos tipos distintos.

2.2.1.

Tipos entero y flotante

Hasta el momento hemos utilizado fundamentalmente datos de tipo entero, es decir, sin
decimales. Solo ocasionalmente hemos visto datos de tipo flotante, normalmente como resultado
de trabajar con el operador de divisin convencional. Pero no solo podemos producir datos de tipo
flotante con el operador de divisin convencional: el resto de operadores produce un resultado
cuyo tipo depende del tipo de sus operandos. La suma, por ejemplo, produce un resultado de
tipo entero si sus dos operandos son de tipo entero, pero produce un valor de tipo flotante si
uno cualquiera de sus operandos es de tipo flotante:

Python sigue una regla sencilla: si hay datos de tipos distintos, el resultado es del tipo ms
general. Los flotantes son de tipo ms general que los enteros.
Hay diferencias entre enteros y reales en Python ms all de que los primeros no tengan
decimales y los segundos s. El nmero 3 y el nmero 3.0, por ejemplo, son indistinguibles
matemticamente, pero diferentes en Python. Qu diferencias hay?
Los enteros suelen ocupar menos memoria.

Las operaciones entre enteros son, generalmente, ms rpidas.

As pues, utilizaremos enteros a menos que de verdad necesitemos nmeros con decimales.
Hemos de precisar algo respecto a la denominacin de los nmeros con decimales: el trmino
reales no es adecuado, ya que induce a pensar en los nmeros reales de las matemticas. En
matemticas, los nmeros reales pueden presentar infinitos decimales, y eso es imposible en un
computador. Al trabajar con computadores tendremos que conformarnos con meras aproximaciones
a los nmeros reales.
Recuerda que todo en el computador son secuencias de ceros y unos. Deberemos, pues,
representar internamente con ellos las aproximaciones a los nmeros reales. Para facilitar el
intercambio de datos, todos los computadores convencionales utilizan una misma codificacin, es
decir, representan del mismo modo las aproximaciones a los nmeros reales. Esta codificacin se
conoce como IEEE Standard 754 floating point (que se puede traducir por Estndar IEEE 754
para coma flotante), as que llamaremos nmeros en formato de coma flotante o simplemente
flotantes a los nmeros con decimales que podemos representar con el ordenador.
Un nmero flotante debe especificarse siguiendo ciertas reglas. En principio, consta de dos
partes: mantisa y exponente. El exponente, que debe ser entero, se separa de la mantisa con la
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

letra e (o E). Por ejemplo, el nmero flotante 2e3 (o 2E3) tiene mantisa 2 y exponente 3, y
representa al nmero 2 103 , es decir, 2000.0.
El exponente puede ser negativo: 3.2e 3 es 3.2 103 , o sea, 0.0032. Ten en cuenta que si un
nmero flotante no lleva exponente debe llevar parte fraccionaria.
Ah! Un par de reglas ms: si la parte entera del nmero es nula, el flotante puede empezar
directamente con un punto, y si la parte fraccionaria es nula, puede acabar con un punto. Veamos
un par de ejemplos: el nmero 0.1 se puede escribir tambin como .1; por otra parte, el nmero
2.0 puede escribirse como 2., es decir, en ambos casos el cero es opcional.
Demasiadas reglas? No te preocupes, con la prctica acabars recordndolas.
IEEE Standard 754

Un nmero en coma flotante presenta tres componentes: el signo, la mantisa y el exponente.


He aqu un nmero en coma flotante: 14.1 103 . El signo es negativo, la mantisa es 14.1 y el
exponente es 3. Los nmeros en coma flotante normalizada presentan una mantisa mayor o igual
que 1 y menor que 10. El mismo nmero de antes, en coma flotante normalizada, es 1.41 102 .
Una notacin habitual para los nmeros en coma flotante sustituye el producto () y la base del
exponente por la letra e o E. Notaramos con 1.41e 2 el nmero del ejemplo.
Los flotantes de Python siguen la norma IEEE Standard 754. Es una codificacin binaria y
normalizada de los nmeros en coma flotante y, por tanto, con base 2 para el exponente y mantisa de
valor mayor o igual que 1 y menor que 2. Usa 32 bits (precisin simple) o 64 bits (precisin doble)
para codificar cada nmero. Python utiliza el formato de doble precisin. En el formato de precisin
doble se reserva 1 bit para el signo del nmero, 11 para el exponente y 52 para la mantisa. Con
este formato pueden representarse nmeros tan prximos a cero como 10323 (322 ceros tras el punto
decimal y un uno) o de valor absoluto tan grande como 10308 .
No todos los nmeros tienen una representacin exacta en el formato de coma flotante. Un nmero
como 0.1 no puede representarse exactamente como flotante. Su mantisa, que vale 1/10, corresponde
a la secuencia peridica de bits
No hay, pues, forma de representar 1/10 con los 52 bits del formato de doble precisin. En base 10,
los 52 primeros bits de la secuencia nos proporcionan el valor
0.1000000000000000055511151231257827021181583404541015625

Es lo ms cerca de 1/10 que podemos estar.


Una peculiaridad adicional de los nmeros codificados con la norma IEEE 754 es que su precisin
es diferente segn el nmero representado: cuanto ms prximo a cero, mayor es la precisin. Para
nmeros muy grandes se pierde tanta precisin que no hay decimales (ni unidades, ni decenas. . . !). Por
ejemplo, el resultado de la suma 100000000.0 0.000000001 es 100000000.0, y no 100000000.000000001,
como cabra esperar.
A modo de conclusin, has de saber que al trabajar con nmeros flotantes es posible que se
produzcan pequeos errores en la representacin de los valores y durante los clculos. Probablemente
esto te sorprenda, pues es vox populi que los ordenadores nunca se equivocan.

2.2.2.

El tipo de datos booleano (y sus operadores)

Hay otro tipo de datos que has de conocer, pues se usa muy frecuentemente en programacin:
el tipo de datos lgico o booleano, llamado as por ser propio del lgebra de Boole3 . Un dato de
tipo lgico solo puede presentar uno de dos valores: True o False, es decir, verdadero o falso.
Hay tres operadores lgicos en Python: la y lgica o conjuncin (and), la o lgica o
disyuncin (or) y el no lgico o negacin (not).
El operador and da como resultado True si y solo si son True sus dos operandos. Esta es
su tabla de verdad:
3 Boole es el matemtico que invent (o descubri?) el lgebra que lleva su nombre y que se basa en el uso de dos
valores (cierto y falso) y tres operadores (negacin, conjuncin y disyuncin).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

and

operandos
izquierdo derecho
True
True
False
False

True
False
True
False

resultado
True
False
False
False

El operador or proporciona True si cualquiera de sus operandos es True, y False solo cuando
ambos operandos son False. Esta es su tabla de verdad:
or

operandos
izquierdo derecho
True
True
False
False

True
False
True
False

resultado
True
True
True
False

El operador not es unario, y proporciona el valor True si su operando es False y viceversa. He


aqu su tabla de verdad:
not

operando
True
False

resultado
False
True

Podemos combinar valores lgicos y operadores lgicos para formar expresiones lgicas. He aqu
algunos ejemplos:

Has de tener en cuenta la precedencia de los operadores lgicos, que se muestra en la


tabla 2.2.
Operacin

Operador

Aridad

Asociatividad

Precedencia

Negacin
not
Unario
alta
................................................................
Conjuncin
and
Binario Por la izquierda
media
................................................................
Disyuncin
or
Binario Por la izquierda
baja

Tabla 2.2: Aridad, asociatividad y precedencia de los operadores lgicos.

Del mismo modo que hemos usado rboles sintcticos para entender el proceso de clculo
de los operadores aritmticos sobre valores enteros y flotantes, podemos recurrir a ellos para
interpretar el orden de evaluacin de las expresiones lgicas. He aqu el rbol sintctico de la
expresin True or False and not False:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

True

or True
False

and False

not True

False

Hay una familia de operadores que devuelven valores booleanos. Entre ellos tenemos a los
operadores de comparacin, que estudiamos en este apartado. Uno de ellos es el operador de
igualdad, que devuelve True si los valores comparados son iguales. El operador de igualdad se
denota con dos iguales seguidos: . Vemoslo en funcionamiento:

Observa la ltima expresin evaluada: es posible combinar operadores de comparacin y operadores aritmticos. No solo eso, tambin podemos combinar en una misma expresin operadores
lgicos, aritmticos y de comparacin:
Este es el rbol sintctico correspondiente a esa expresin:

True

booleano True

or booleano True
2

booleano False

True

entero 3
2

Hemos indicado junto a cada nodo interior el tipo del resultado que corresponde a su subrbol.
Como ves, en todo momento operamos con tipos compatibles entre s.
Antes de presentar las reglas de asociatividad y precedencia que son de aplicacin al combinar diferentes tipos de operador, te presentamos todos los operadores de comparacin en la
tabla 2.3 y te mostramos algunos ejemplos de uso:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

operador

comparacin
es
es
es
es
es
es

distinto de
igual que
menor que
menor o igual que
mayor que
mayor o igual que

Tabla 2.3: Operadores de comparacin.

Es hora de que presentemos una tabla completa (tabla 2.4) con todos los operadores que
conocemos para comparar entre s la precedencia de cada uno de ellos cuando aparece combinado
con otros.
Operacin

Operador

Aridad

Asociatividad

Precedencia

Exponenciacin
Binario Por la derecha
1
.............................................................................
Unario

2
Identidad
Unario

2
Cambio de signo
.............................................................................
Binario Por la izquierda
3
Multiplicacin
Binario Por la izquierda
3
Divisin
Binario Por la izquierda
3
Divisin entera
Mdulo (o resto)
Binario Por la izquierda
3
.............................................................................
Binario Por la izquierda
4
Suma
Binario Por la izquierda
4
Resta
.............................................................................
Binario

5
Igual que
Binario

5
Distinto de
Binario

5
Menor que
Binario

5
Menor o igual que
Mayor que
Binario

5
Binario

5
Mayor o Igual que
.............................................................................
Unario

6
Negacin
.............................................................................
Binario Por la izquierda
7
Conjuncin
.............................................................................
Binario Por la izquierda
8
Disyuncin

Tabla 2.4: Caractersticas de los operadores Python. El nivel de precedencia 1 es el de mayor


prioridad.

En la tabla 2.4 hemos omitido cualquier referencia a la asociatividad de los comparadores


de Python, pese a que son binarios. Python es un lenguaje peculiar en este sentido. Imaginemos
que fueran asociativos por la izquierda. Qu significara esto? El operador suma, por ejemplo,
3
4 se procede as:
es asociativo por la izquierda. Al evaluar la expresin aritmtica 2
primero se suma el 2 al 3; a continuacin, el 5 resultante se suma al 4 y se obtiene un total de 9.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Si el operador fuese asociativo por la izquierda, la expresin lgica 2


3
4 se evaluara
as: primero, se compara el 2 con el 3, resultando el valor True; a continuacin, se compara el
4? No tiene sentido.
resultado obtenido con el 4, pero qu significa la expresin True
Cuando aparece una sucesin de comparadores como, por ejemplo, 2
3
4, Python la
3 and 3
4 . Esta solucin permite expresar condiciones complejas
evala igual que 2
de modo sencillo y, en casos como el de este ejemplo, se lee del mismo modo que se leera con
la notacin matemtica habitual, lo cual parece deseable. Pero ojo! Python permite expresiones
3
1, o 2
3
5.
que son ms extraas; por ejemplo, 2
Una rareza de Python: la asociatividad de los comparadores

Algunos lenguajes de programacin de uso comn, como C y C++, hacen que sus operadores de
comparacin sean asociativos, por lo que presentan el problema de que expresiones como
producen un resultado que parece ilgico. Al ser asociativo por la izquierda el operador de comparacin , se evala primero la subexpresin
. El resultado es falso, que en C y C se representa
con el valor 0. A continuacin se evala la comparacin
, cuyo resultado es. . . cierto! As pues,
para C y C es cierto que
.
Pascal es ms rgido an y llega a prohibir expresiones como
. En Pascal hay un tipo
de datos denominado
cuyos valores vlidos son
y
. Pascal no permite operar
entre valores de tipos diferentes, as que la expresin
se evala al valor booleano
, que
no se puede comparar con un entero al tratar de calcular el valor de
. En consecuencia,
se produce un error de tipos si intentamos encadenar comparaciones.
La mayor parte de los lenguajes de programacin convencionales opta por la solucin del C o por
la solucin del Pascal. Cuando aprendas otro lenguaje de programacin, te costar deshabituarte
de la elegancia con que Python resuelve los encadenamientos de comparaciones.

16

2.3.

Qu resultados se muestran al evaluar estas expresiones?

Literales de entero

Ya sabes cmo escribir un nmero entero. . . en base 10. Es lo ms corriente: escribir nmeros
enteros con un sistema en el que cada dgito es un nmero entre 0 y 9, y en el que cada posicin
supone que el dgito vale 10 veces ms que el que hay ms a su derecha. As, el nmero 132
equivale a 1 102 + 3 101 + 2 100 = 1 100 + 3 10 + 2 1. Pero en ocasiones convendr expresar
nmeros con otra base. En informtica es muy comn trabajar con base 2, base 8 y base 16. Es
natural que la base 2 sea usada con relativa frecuencia, pues ya sabes que la informacin se
almacena y manipula a partir de codificaciones binarias. Las otras dos bases son de uso comn
por razones histricas. La base 8 permite manejar nmeros en los que interpretamos que cada
grupo de 3 bits corresponde a un dgito y la base 16 hace lo propio con grupos de 4 bits.
Python permite expresar nmeros en estas tres bases. Los nmeros en base 2 se expresan
con el prefijo 0b (o 0B) seguido de una sucesin de unos y ceros.
Observa que el resultado se muestra en base 10, aunque los nmeros se hayan escrito en
base 2. Tan pronto Python analiza la secuencia 0b10, por ejemplo, considera que ha ledo el
valor 2. Internamente no hay ninguna diferencia entre el resultado de evaluar 2 y 0b10. As pues,
el resultado de evaluar la expresin 0b1
0b0001 es exactamente el mismo que obtenemos al
evaluar 1 1.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Los nmeros en base 8, tambin conocida como base octal, se forman con 0o (o 0O) seguida de
uno o ms dgitos entre 0 y 7. El nmero 0o177 corresponde al nmero decimal 182 +781 +780 =
1 64 + 7 8 + 7 1 = 64 + 56 + 7 = 127.
Finalmente, los nmeros en base 16 o hexadecimal empiezan por 0x (o 0X) y siguen con
uno o ms dgitos entre 0 y 9 o letras minsculas o maysculas entre A y F. La letra A tiene
valor 10, la B valor 11 y as hasta la F, que tiene valor 15. El nmero 0xFA1 corresponde a
15 162 + 10 161 + 1 160 = 15 256 + 10 16 + 1 1 = 4001.
Y si quisisemos ver el resultado en base 2, 8 o 16? Hemos de aprender antes algunas cosas
acerca de las cadenas y las funciones. Antes de acabar este captulo sabremos cmo hacerlo.
17

a) 0xf

b) 0xffff

2.4.

Evala estas expresiones:

0o17

0b1

0b1111

15

Variables y asignaciones

En ocasiones deseamos que el ordenador recuerde ciertos valores para usarlos ms adelante.
Por ejemplo, supongamos que deseamos efectuar el clculo del permetro y el rea de un crculo
de radio 1.298373 m. La frmula del permetro es 2r, donde r es el radio, y la frmula del rea
es r 2 . (Aproximaremos el valor de con 3.14159265359). Podemos realizar ambos clculos del
siguiente modo:
Observa que hemos tenido que introducir dos veces los valores de y r por lo que, al
tener tantos decimales, es muy fcil cometer errores. Para paliar este problema podemos utilizar
variables:

En la primera lnea hemos creado una variable de nombre pi y valor 3.14159265359. A


continuacin, hemos creado otra variable, r, y le hemos dado el valor 1.298373. El acto de dar
valor a una variable se denomina asignacin. Al asignar un valor a una variable que no exista,
Python reserva un espacio en la memoria, almacena el valor en l y crea una asociacin entre
el nombre de la variable y la direccin de memoria de dicho espacio. Podemos representar
grficamente el resultado de estas acciones as:
pi
r

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

3.14159265359
1.298373

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

A partir de ese instante, escribir pi es equivalente a escribir 3.14159265359, y escribir r es


equivalente a escribir 1.298373.
Podemos almacenar el resultado de calcular el permetro y el rea en sendas variables:

pi

3.14159265359

1.298373

permetro

8.157918156839218

rea

5.296010335524904

La memoria se ha reservado correctamente, en ella se ha almacenado el valor correspondiente


y la asociacin entre la memoria y el nombre de la variable se ha establecido, pero no obtenemos
respuesta alguna por pantalla. Debes tener en cuenta que las asignaciones son mudas, es decir,
no provocan salida por pantalla. Si deseamos ver cunto vale una variable, podemos evaluar una
expresin que solo contiene a dicha variable:

As pues, para asignar valor a una variable basta ejecutar una sentencia como esta:
variable

expresin

Ten cuidado: el orden es importante. Hacer expresin


variable no es equivalente. Una asignacin no es una ecuacin matemtica, sino una accin consistente en (por este orden):
1) evaluar la expresin a la derecha del smbolo igual ( ), y

2) guardar el valor resultante en la variable indicada a la izquierda del smbolo igual.


no es

(comparar no es asignar)

Al aprender a programar, muchas personas confunden el operador de asignacin, , con el operador


de comparacin, . El primero se usa exclusivamente para asignar un valor a una variable. El segundo,
para comparar valores.
Observa la diferente respuesta que obtienes al usar y
en el entorno interactivo:

Se puede asignar valor a una misma variable cuantas veces se quiera. El efecto es que la
variable, en cada instante, solo recuerda el ltimo valor asignado. . . hasta que se le asigne
otro.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Una asignacin no es una ecuacin

Hemos de insistir en que las asignaciones no son ecuaciones matemticas, por mucho que su
aspecto nos recuerde a estas. Fjate en este ejemplo, que suele sorprender a aquellos que empiezan
a programar:

La primera lnea asigna a la variable x el valor 3. La segunda lnea parece ms complicada. Si la


interpretas como una ecuacin, no tiene sentido, pues de ella se concluye absurdamente que 3 = 4 o,
sustrayendo la x a ambos lados del igual, que 0 = 1. Pero si seguimos paso a paso las acciones que
ejecuta Python al hacer una asignacin, la cosa cambia:
1) Se evala la parte derecha del igual (sin tener en cuenta para nada la parte izquierda). El valor
de x es 3, que sumado a 1 da 4.

2) El resultado (el 4), se almacena en la variable que aparece en la parte izquierda del igual, es
decir, en x.

As pues, el resultado de ejecutar las dos primeras lneas es que x vale 4.

El nombre de una variable es su identificador. Hay unas reglas precisas para construir
identificadores. Si no se siguen, diremos que el identificador no es vlido. Un identificador debe
estar formado por letras4 minsculas, maysculas, dgitos y/o el carcter de subrayado , con
una restriccin: que el primer carcter no sea un dgito.
Hay una norma ms: un identificador no puede coincidir con una palabra reservada o palabra
clave. Una palabra reservada es una palabra que tiene un significado predefinido y es necesaria
para expresar ciertas construcciones del lenguaje. Aqu tienes una lista con todas las palabras
reservadas de Python: and, as, assert, break, class, continue, def, del, elif, else, except, False,
finally, for, from, global, if, import, in, is, lambda, nonlocal, None, not, or, pass, raise, return,
True, try, with, while y yield.
Por ejemplo, los siguientes identificadores son vlidos: h, x, Z, velocidad, aceleracin, fuerza1,
masa_2, _a, a_, prueba_123, desviacin_tpica. Debes tener presente que Python distingue entre
maysculas y minsculas, as que rea, rea y REA son tres identificadores vlidos y diferentes.
Cualquier carcter diferente de una letra, un dgito o el subrayado es invlido en un identificador, incluyendo el espacio en blanco. Por ejemplo, edad media (con un espacio en medio) son
dos identificadores (edad y media), no uno. Cuando un identificador se forma con dos palabras,
es costumbre de muchos programadores usar el subrayado para separarlas: edad_media; otros
programadores utilizan una letra mayscula para la inicial de la segunda: edadMedia. Escoge
el estilo que ms te guste para nombrar variables, pero permanece fiel al que escojas.
Dado que eres libre de llamar a una variable con el identificador que quieras, hazlo con
clase: escoge siempre nombres que guarden relacin con los datos del problema. Si, por ejemplo,
vas a utilizar una variable para almacenar una distancia, llama a la variable distancia y evita
nombres que no signifiquen nada; de este modo, los programas sern ms legibles.
18

Son vlidos los siguientes identificadores?

a) Identificador
4 Son

letras vlidas las de cualquier alfabeto. As, es un identificador vlido por ser una letra del alfabeto griego.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

b) Indice dos

c) Dos palabras

d) __

e) 12horas
f) hora12

g) desviacin
h) ao

i) from
j) var!

k)

l) import_from

m) UnaVariable
n) a b
) 12

o) uno dos

p) x

q)

r) rea

s) area rect

t) x_______1

u) ________1
v) _x_

w) x_x
19

Qu resulta de ejecutar estas tres lneas?

20
Evala el polinomio x 4 + x 3 + 2x 2 x en x = 1.1. Utiliza variables para evitar teclear
varias veces el valor de x. (El resultado es 4.1151).
21

Evala el polinomio x 4 + x 3 + 12 x 2 x en x = 10. (El resultado es 11040.0).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

2.4.1.

Asignaciones con operador

Fjate en la sentencia i
i
1: aplica un incremento unitario al contenido de la variable i.
Incrementar el valor de una variable en una cantidad cualquiera es tan frecuente que existe una
forma compacta en Python. El incremento de i puede denotarse as: i
1 (sin espacio alguno
entre el y el ). Puedes incrementar una variable con cualquier cantidad, incluso con una que
resulte de evaluar una expresin:

Todos los operadores aritmticos tienen su asignacin con operador asociada.

Hemos de decirte que estas formas compactas no aportan nada nuevo. . . salvo comodidad,
as que no te preocupes por tener que aprender tantas cosas. Si te vas a sentir incmodo por tener
que tomar decisiones y siempre ests pensando uso ahora la forma normal o la compacta?,
ser mejor que ignores de momento las formas compactas.
22

2.4.2.

Qu valor tiene z tras evaluar estas sentencias?

Variables no inicializadas

En Python, la primera operacin sobre una variable debe ser la asignacin de un valor. No
se puede usar una variable a la que no se ha asignado previamente un valor:

Como puedes ver, se genera una excepcin


, es decir, de error de nombre.
, es decir, el
El texto explicativo precisa an ms lo sucedido:
nombre a no est definido.
La asignacin de un valor inicial a una variable se denomina inicializacin de la variable.
Decimos, pues, que en Python no es posible usar variables no inicializadas.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ms operadores

Solo te hemos presentado los operadores que utilizaremos en el texto y que ya ests preparado
para manejar. Pero has de saber que hay ms operadores. Hay operadores, por ejemplo, que estn
dirigidos a manejar las secuencias de bits que codifican los valores enteros. El operador binario
calcula la operacin y bit a bit, el operador binario calcula la operacin o bit a bit, el operador
binario calcula la o exclusiva (que devuelve cierto si y solo si los dos operandos son distintos),
tambin bit a bit, y el operador unario invierte los bits de su operando. Tienes, adems, los operadores
binarios
y , que desplazan los bits a izquierda o derecha tantas posiciones como le indiques.
Estos ejemplos te ayudarn a entender estos operadores:
En decimal
Expresin Resultado
5 & 12
5 12
5 ^ 12
5
1
5
2
5
3
5
1

4
13
9
10
20
40
2

En binario
Expresin
Resultado

Y estos operadores presentan, adems, una forma compacta con asignacin:


, , etc.!
Ms adelante estudiaremos, adems, los operadores is (e is not) e in (y not in), los operadores
de indexacin, de llamada a funcin, de corte. . .

2.5.

El tipo de datos cadena

Hasta el momento hemos visto que Python puede manipular datos numricos de dos tipos:
enteros y flotantes. Pero Python tambin puede manipular otros tipos de datos. Vamos a estudiar
ahora el tipo de datos que se denomina cadena. Una cadena es una secuencia de caracteres
(letras, nmeros, espacios, marcas de puntuacin, etc.) y en Python se distingue porque va encerrada entre comillas simples o dobles . Por ejemplo,
,
,
,
,
son cadenas. Observa que los espacios en blanco se muestran as en este
texto: . Lo hacemos para que resulte fcil contar los espacios en blanco cuando haya ms de
. Si no
uno seguido. Esta cadena, por ejemplo, est formada por tres espacios en blanco:
los representsemos con las cajitas, sera difcil contarlos.
Las cadenas pueden usarse para representar informacin textual: nombres de personas, nombres de colores, matrculas de coche. . . Las cadenas tambin pueden almacenarse en variables.

nombre

Es posible realizar operaciones con cadenas. Por ejemplo, podemos sumar cadenas aadiendo una a otra.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Una cadena no es un identificador

Con las cadenas tenemos un problema: muchas personas que estn aprendiendo a programar
confunden una cadena con un identificador de variable y viceversa. No son la misma cosa. Fjate bien
en lo que ocurre:

La primera lnea asigna a la variable a el valor 1. Como a es el nombre de una variable, es


decir, un identificador, no va encerrado entre comillas. A continuacin hemos escrito
y Python
ha respondido tambin con
: la a entre comillas es una cadena formada por un nico carcter, la
letra a, y no tiene nada que ver con la variable a. A continuacin hemos escrito la letra a sin
comillas y Python ha respondido con el valor 1, que es lo que contiene la variable a.
Muchos estudiantes de programacin cometen errores como estos:
Quieren utilizar una cadena, pero olvidan las comillas, con lo que Python cree que se quiere
usar un identificador; si ese identificador no existe, da un error:

Quieren usar un identificador pero, ante la duda, lo encierran entre comillas:

Recuerda: solo se puede asignar valores a variables, nunca a cadenas, y las cadenas no son identificadores.

Hablando con propiedad, esta operacin no se llama suma, sino concatenacin. El smbolo
utilizado es , el mismo que usamos cuando sumamos enteros y/o flotantes; pero aunque el
smbolo sea el mismo, ten en cuenta que no es igual sumar nmeros que concatenar cadenas:
Sumar o concatenar una cadena y un valor numrico (entero o flotante) produce un error:
Y para acabar, hay un operador de repeticin de cadenas. El smbolo que lo denota es ,
el mismo que hemos usado para multiplicar enteros y/o flotantes. El operador de repeticin
necesita dos datos: uno de tipo cadena y otro de tipo entero. El resultado es la concatenacin
de la cadena consigo misma tantas veces como indique el nmero entero:

23
Evala estas expresiones y sentencias en el mismo orden en el que aparecen e indica
lo que muestra el intrprete de Python como respuesta.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

24
Qu resultados se obtendrn al evaluar las siguientes expresiones y asignaciones
Python? Calcula primero a mano el valor resultante de cada expresin y comprueba, con la ayuda
del ordenador, si tu resultado es correcto.

25
Identifica regularidades en las siguientes cadenas, y escribe expresiones que, partiendo de subcadenas ms cortas y utilizando los operadores de concatenacin y repeticin,
produzcan las cadenas que se muestran. Introduce variables para formar las expresiones cuando
lo consideres oportuno.
a)

b)
c)

d)

2.6.

Funciones predefinidas

2.6.1.

Algunas funciones sobre valores numricos

Hemos estudiado los operadores aritmticos bsicos. Python tambin proporciona funciones
que podemos utilizar en las expresiones. Estas funciones se dice que estn predefinidas5 .

La funcin abs, por ejemplo, calcula el valor absoluto de un nmero. Podemos usarla como
en estas expresiones:
El nmero sobre el que se aplica la funcin se denomina argumento. Observa que el argumento de la funcin debe ir encerrado entre parntesis:

Existen muchas funciones predefinidas, pero es pronto para aprenderlas todas. Te resumimos
algunas que ya puedes utilizar:
5 Predefinidas

porque nosotros tambin podemos definir nuestras propias funciones. Ya llegaremos.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

float: conversin a flotante. Si recibe un nmero entero como argumento, devuelve el mismo
nmero convertido en un flotante equivalente.
La funcin float tambin acepta argumentos de tipo cadena. Cuando se le pasa una cadena,
float la convierte en el nmero flotante que esta representa:

Pero si la cadena no representa un flotante, se produce un error de tipo


decir, error de valor:

, es

Si float recibe un argumento flotante, devuelve el mismo valor que se suministra como
argumento.
int: conversin a entero. Si recibe un nmero flotante como argumento, devuelve el entero
que se obtiene eliminando la parte fraccionaria.6

La funcin int acepta como argumento una cadena:


Si int recibe un argumento entero, devuelve un entero con el valor del argumento, tal cual.
str: conversin a cadena. Recibe un nmero y devuelve una representacin de este como
cadena.

La funcin str tambin puede recibir como argumento una cadena, pero en ese caso devuelve
como resultado la misma cadena.

6 El redondeo de int puede ser al alza o a la baja segn el ordenador en que lo ejecutes. Esto es as porque int se
apoya en el comportamiento del redondeo automtico de C (el intrprete de Python que usamos est escrito en C) y
su comportamiento est indefinido. Si quieres un comportamiento homogneo del redondeo, puedes usar las funciones
round, floor o ceil, que se explican ms adelante.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

bin: representacin en binario. Convierte un nmero entero en una cadena con el nmero
expresado en base 2.

oct: representacin en octal. Convierte un nmero entero en una cadena con el nmero
expresado en base 8.

hex: representacin en hexadecimal. Convierte un nmero entero en una cadena con el


nmero expresado en base 16.

round: redondeo. Puede usarse con uno o dos argumentos. Si se usa con un solo argumento,
redondea el nmero al entero ms prximo.

(Observa que el resultado siempre es de tipo entero!) Si round recibe dos argumentos,
estos deben ir separados por una coma y el segundo indica el nmero de decimales que
deseamos conservar tras el redondeo.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Estas funciones (y las que estudiaremos ms adelante) pueden formar parte de expresiones y
sus argumentos pueden, a su vez, ser expresiones. Observa los siguientes ejemplos:

26
es 3).

Calcula con una nica expresin el valor absoluto del redondeo de 3.2. (El resultado

27
Convierte (en una nica expresin) a una cadena el resultado de la divisin 5011/10000
redondeado con 3 decimales.
28

2.6.2.

Qu resulta de evaluar estas expresiones?

Dos funciones bsicas para cadenas: ord y chr

El concepto de comparacin entre nmeros te resulta familiar porque lo has estudiado antes
en matemticas. Python extiende el concepto de comparacin a otros tipos de datos, como las
y
el significado est claro: dos cadenas son iguales
cadenas. En el caso de los operadores
si son iguales carcter a carcter, y distintas en caso contrario. Pero qu significa que una
cadena sea menor que otra? Python utiliza un criterio de comparacin de cadenas similar al
orden alfabtico.
Cuando Python compara dos cadenas lo hace carcter a carcter. Cada carcter es un entero
de 16 bits. La letra a, por ejemplo, se codifica con el entero 97, y la b con el entero 98. Si
comparamos la cadena
con la cadena
, Python nos dir que la primera es menor que la
con
? Python compara primero el primer carcter
segunda. Qu pasa si comparamos
de cada cadena. Como los dos son iguales, pasa a comparar el segundo carcter de cada cadena
y llega a la conclusin de que la primera cadena es menor que la segunda. Y qu pasa si
comparamos
con
? Nuevamente el primer carcter resulta insuficiente para decidir
nada. Python trata de pasar a estudiar el segundo carcter de cada cadena, pero la primera
cadena no tiene segundo carcter. As pues, nuevamente resulta que la primera cadena es menor
que la segunda.
En principio, una cadena es menor que otra si la debe preceder al disponerlas en un diccioes menor que
. Pero solo en principio. Fjate en que la
nario. Por ejemplo,
letra b mayscula tiene cdigo 66. Eso significa que Barco es menor que ancla:
Las letras acentuadas plantean problemas similares, pues tienen valores numricos mayores
que sus versiones sin acentuar:
Para conocer el valor numrico que corresponde a un carcter, puedes utilizar la funcin
predefinida ord, a la que le has de pasar el carcter en cuestin como argumento.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

De ASCII a Unicode

Hace algunos aos era corriente codificar cada carcter con un byte (ocho bits). La tabla que
estableca la correspondencia entre carcter y valor numrico era la denominada tabla ASCII, de la
que hemos hablado brevemente en el primer captulo. La letra a, por ejemplo, tiene valor numrico 97.
En realidad no codificaba 256 smbolos, sino solo 128: los que correspondan a valores numricos
entre 0 y 127. Esta tabla, diseada en 1968, era problemtica en pases como el nuestro, pues no
recoga los caracteres acentuados o la letra ee. Con 256 caracteres, que es lo que podemos codificar
con 8 bits, era imposible tener un juego completo vlido para todos los pases del mundo. De hecho,
ni siquiera para todos los pases europeos.
Cada sistema informtico extendi la tabla ASCII a su gusto. Usualmente se aadan caracteres
a los 128 valores no usados por la tabla ASCII. Esto trajo multitud de problemas a la hora de intercambiar archivos de texto entre sistemas. En los aos 90, una comisin estandariz tablas adaptadas
a diferentes dominios lingsticos. La tabla apropiada para Europa occidental era la denominada
ISO-8859-1, tambin conocida como IsoLatin1 o Latin1. Pronto esta tabla se qued corta: el smbolo
del euro no estaba contemplado en ella. La tabla ISO-8859-15 ampliaba la ISO-8859-1 para recoger
el smbolo del euro.
El problema de codificar la informacin textual estaba lejos de quedar satisfactoriamente resuelto
si haba que recurrir a multitud de tablas de 256 caracteres. Pinsese en que era imposible, por
ejemplo, incluir en un nico fichero de texto un fragmento en espaol con otro en japons.
Surgi entonces una codificacin capaz de resolver el problema definitivamente: la codificacin
Unicode. Unicode empez planteando que cada carcter deba codificarse con 16 bits y no con solo 8.
Esto haca que hubiera 65536 cdigos disponibles. Como seguan siendo insuficientes para representar
cualquier carcter de cualquier lengua, Unicode defini codificaciones con nmero de bits variable
que permitieran, mediante sucesivas extensiones, dar cuenta de cualquier alfabeto existente.
Nosotros consideraremos que cada carcter se representa con un nmero de 16 bits y no entraremos
en ms detalles sobre Unicode. Python, desde las versiones 3.0 en adelante, representa las cadenas
con Unicode.

La funcin chr hace lo contrario: devuelve un carcter, dado su valor numrico.

29

Qu resultados se muestran al evaluar estas expresiones?

2.7.

Mdulos e importacin de funciones y variables

2.7.1.

El mdulo math

Python tambin proporciona funciones trigonomtricas, logaritmos, etc., pero no estn directamente disponibles cuando iniciamos una sesin. Antes de utilizarlas hemos de indicar a Python
que vamos a hacerlo. Para ello, importamos cada funcin de un mdulo.
Empezaremos por importar la funcin seno (sin, del ingls sinus) del mdulo matemtico
(math):

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ahora podemos utilizar la funcin en nuestros clculos:

Observa que el argumento de la funcin seno debe expresarse en radianes.


Inicialmente Python no sabe calcular la funcin seno. Cuando importamos una funcin,
Python aprende su definicin y nos permite utilizarla. Las definiciones de funciones residen
en mdulos. Las funciones trigonomtricas residen en el mdulo matemtico. Por ejemplo, la
funcin coseno, en este momento, es desconocida para Python.
Antes de usarla, es necesario importarla del mdulo matemtico:
En una misma sentencia podemos importar ms de una funcin. Basta con separar sus
nombres con comas:

Puede resultar tedioso importar un gran nmero de funciones y variables de un mdulo.


Python ofrece un atajo: si utilizamos un asterisco, se importan todos los elementos proporcionados
por un mdulo. Para importar todos los elementos del mdulo math escribimos:
As de fcil. De todos modos, no resulta muy aconsejable por dos razones:

Al importar elemento a elemento, el programa gana en legibilidad, pues sabemos de dnde


proviene cada identificador.

Si hemos definido una variable con un nombre determinado y dicho nombre coincide con
el de una funcin definida en un mdulo, nuestra variable ser sustituida por la funcin.
Si no sabes todos los elementos que define un mdulo, es posible que esta coincidencia
de nombre tenga lugar, te pase inadvertida inicialmente y te lleves una sorpresa cuando
intentes usar la variable.

He aqu un ejemplo del segundo de los problemas indicados:

Python se queja de que intentamos sumar un entero y una funcin. Efectivamente, hay una
funcin pow en el mdulo math. Al importar todo el contenido de math, nuestra variable ha sido
machacada por la funcin.
Te presentamos algunas de las funciones que encontrars en el mdulo matemtico:
sin(x)
cos(x)
tan(x)
exp(x)
ceil(x)
floor(x)
log(x)
log10(x)
sqrt(x)

Seno de x, que debe estar expresado en radianes.


Coseno de x, que debe estar expresado en radianes.
Tangente de x, que debe estar expresado en radianes.
El nmero e elevado a x.
Redondeo hacia arriba de x (en ingls, ceiling significa techo).
Redondeo hacia abajo de x (en ingls, floor significa suelo).
Logaritmo natural (en base e) de x.
Logaritmo decimal (en base 10) de x.
Raz cuadrada de x (del ingls square root).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Evitando las coincidencias

Python ofrece un modo de evitar el problema de las coincidencias: indicar solo el nombre del
mdulo al importar.
De esta forma, todas las funciones del mdulo math estn disponibles, pero usando el nombre del
mdulo y un punto como prefijo:

En el mdulo matemtico se definen, adems, algunas constantes de inters:

30
Qu resultados se obtendrn al evaluar las siguientes expresiones Python? Calcula
primero a mano el valor resultante de cada expresin y comprueba, con la ayuda del ordenador,
si tu resultado es correcto.
a) int exp 2

log 3

b) round 4 sin 3

pi

d) round 3.21123

log10 1000

c) abs log10 .01

sqrt 25

3
Precisin de los flotantes

Hemos dicho que los argumentos de las funciones trigonomtricas deben expresarse en radianes.
Como sabrs, sen() = 0. Veamos qu opina Python:
El resultado que proporciona Python no es cero, sino un nmero muy prximo a cero:
0.00000000000000012246467991473532. Se ha equivocado Python? No exactamente. Ya dijimos antes
que los nmeros flotantes tienen una precisin limitada. El nmero est definido en el mdulo matemtico como 3.141592653589793115997963468544185161590576171875, cuando en realidad posee
un nmero infinito de decimales. As pues, no hemos pedido exactamente el clculo del seno de ,
sino el de un nmero prximo, pero no exactamente igual. Por otra parte, el mdulo matemtico hace
clculos mediante algoritmos que pueden introducir errores en el resultado. Fjate en el resultado de
esta sencilla operacin:
Los resultados con nmeros en coma flotante deben tomarse como meras aproximaciones de los
resultados reales.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

2.7.2.

Otros mdulos de inters

Existe un gran nmero de mdulos, cada uno de ellos especializado en un campo de aplicacin determinado. Precisamente, una de las razones por las que Python es un lenguaje potente
y extremadamente til es por la gran coleccin de mdulos con que se distribuye. Hay mdulos
para el diseo de aplicaciones para web, diseo de interfaces de usuario, compresin de datos,
criptografa, multimedia, etc. Y constantemente aparecen nuevos mdulos: cualquier programador
de Python puede crear sus propios mdulos, aadiendo as funciones que simplifican la programacin en un mbito cualquiera y ponindolas a disposicin de otros programadores. Nos
limitaremos a presentarte ahora unas pocas funciones de un par de mdulos interesantes.
Vamos con otro mdulo importante: sys (sistema), el mdulo de sistema (sys es una abreviatura del ingls system). Este mdulo contiene funciones que acceden al sistema operativo
y constantes dependientes del computador. Una funcin importante es exit, que aborta inmediatamente la ejecucin del intrprete (en ingls significa salir). La variable version, indica con
qu versin de Python estamos trabajando:
Y la variable platform permite saber sobre qu sistema operativo se est ejecutando el
intrprete:
Ojo! Con esto no queremos decirte que las variables version o platform sean importantsimas
y que debas aprender de memoria su nombre y cometido, sino que los mdulos de Python contienen centenares de funciones y variables tiles para diferentes propsitos. Un buen programador
Python sabe manejarse con los mdulos. Existe un manual de referencia que describe todos
los mdulos estndar de Python. Lo encontrars con la documentacin Python bajo el nombre
Library reference (en ingls significa referencia de biblioteca) y podrs consultarla con un
navegador web.

2.8.

Mtodos

2.8.1.

Unos mtodos sencillos para manipular cadenas. . .

Los datos de ciertos tipos permiten invocar unas funciones especiales: los denominados
mtodos. Hemos visto que las funciones se invocan as: funcin argumento1 argumento2
argumento3. . . ). Los mtodos son funciones especiales, pues se invocan del siguiente modo:
argumento1 mtodo argumento2 argumento3. . . ). Esta sintaxis recalca el hecho de que, para
un mtodo, el primer argumento es muy especial. Es como el sujeto de una frase de la que el
mtodo es el verbo.
Un mtodo permite, por ejemplo, obtener una versin en minsculas de la cadena sobre la
que se invoca:

La sintaxis es diferente de la propia de una llamada a funcin convencional. Lo primero que


aparece es el propio objeto sobre el se efecta la llamada. El nombre del mtodo se separa del
objeto con un punto. Los parntesis abierto y cerrado al final son obligatorios.
Existe otro mtodo, upper (uppercase, en ingls, significa maysculas), que pasa todos
los caracteres a maysculas.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Y otro, title, que pasa la inicial de cada palabra a maysculas. Te preguntars para qu
puede valer esta ltima funcin. Imagina que has hecho un programa de recogida de datos que
confecciona un censo de personas y que cada individuo introduce personalmente su nombre
en el ordenador. Es muy probable que algunos utilicen solo maysculas y otros maysculas y
minsculas. Si aplicamos title a cada uno de los nombres, todos acabarn en un formato nico:
Algunos mtodos aceptan argumentos. El mtodo replace, por ejemplo, recibe como argumento
dos cadenas: un patrn y un reemplazo. El mtodo busca el patrn en la cadena sobre la que
se invoca el mtodo y sustituye todas sus apariciones por la cadena de reemplazo.

Complejos, decimales y fracciones

Python posee un rico conjunto de tipos de datos. Algunos, como los tipos de datos estructurados,
se estudiarn con detalle ms adelante. Sin embargo, y dado el carcter introductorio de este texto, no
estudiaremos con detalle otros tipos de datos bsicos: los nmeros complejos, los nmeros en formato
decimal y las fracciones.

Un nmero complejo puro finaliza siempre con la letra jota, que representa el valor 1. Un
nmero complejo con parte real se expresa sumando la parte real a un complejo puro. He aqu ejemplos
de nmeros complejos: 4j, 1
2j, 2.0
3j, 1
0.354j. Y, para acabar, un ejemplo de expresiones
aritmticas con complejos:

Los nmeros de tipo decimal dan una solucin al problema de la imprecisin de los flotantes. Esta
imprecisin es inaceptable cuando manejamos, por ejemplo, dinero. El tipo Decimal, que hemos de
importar del mdulo decimal, maneja decimales con precisin:

Otro modo de abordar el problema de la imprecisin de los flotantes es usar el tipo Fraction, que
permite manipular nmeros formados por un numerador y un denominador:

Tanto Decimal como Fraction son sensiblemente ms lentos que los flotantes. No nos poda salir
gratis!

2.8.2.

. . . y uno mucho ms complejo: format

Aprender a mostrar la informacin con formato es esencial para que el usuario encuentre
atractiva la forma en que ve los resultados. El mtodo format de las cadenas nos proporciona
una herramienta fundamental, aunque cuesta un poco dominarlo.
Empezamos por aprender a interpolar valores en una cadena, es decir, sustituir una marca
especial por el valor de una expresin. Fjate en esta sentencia:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Los caracteres
de otro modo:

han sido reemplazados por los caracteres

. Ya sabamos hacer esto

El mtodo format presenta algunas ventajas: su uso conduce a una expresin ms breve y el
nmero 1.23 se ha podido suministrar como nmero (cuando replace exige que sea una cadena).
Pero las ventajas no acaban ah. Podemos interporlar ms de un valor con una sola llamada a
format:
Cada marca de la forma n , donde n es un nmero entero, se sustituye por un argumento de
se ha sustituido por el primer argumento y la marca
por el segundo. En
format: la marca
general, la marca n se sustituye por el argumento (n + 1)-simo. No habra sido ms sencillo
hiciese referencia al primer argumento,
al segundo y
para el diseador de Python que
as sucesivamente? Ya te acostumbrars a un principio bsico de Python: todas las secuencias
empiezan en cero. (Y no solo de Python: tambin C, Java y la mayora de los lenguajes de uso
comn comparten ese principio).
Las marcas pueden disponerse dentro de la cadena en el orden que desees:
31

Cul ser el resultado de evaluar estas expresiones?

Las marcas pueden modificarse para controlar el aspecto de la informacin. Imaginemos que
deseamos mostrar los valores flotantes redondeados con un solo decimal:
Complicado? Las marcas, a las que denominaremos en adelante marcas de formato, permiten
controlar con precisin el modo en el que se muestran los datos. La forma general de una marca
de formato es esta:
campo marca de conversin formato

El campo es el nmero que identifica el nmero de argumento que se desea interpolar en


la cadena (aunque admite otros valores). Olvidemos por el momento el fragmento marca de
conversin y centrmonos en la parte formato. Su forma general es esta:
[[relleno]alineamiento][signo][ ][0][ancho][ precisin][cdigo de tipo]

Cada elemento entre corchetes es opcional. Es decir, el fragmento signo puede aparecer o no.
Fjate en que los corchetes se anidan en uno de los fragmentos. De acuerdo con ese anidamiento,
una marca de formato puede empezar por un relleno o no hacerlo, pero solo puede tener un relleno
si aparece tambin un alineamiento. Y ahora veamos algunas posibilidades para cada uno de
esos elementos:

relleno: Carcter con el que rellenar los espacios que requiere un alineamiento (por defecto,
espacio en blanco).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

alineamiento: Carcter para alinear a la izquierda en el espacio disponible; carcter


para alinear a la derecha en el espacio disponible (es el valor por defecto); carcter
para centrar en el espacio disponible.

signo: Carcter para forzar la aparicin de un signo incluso en nmeros positivos; carcter para indicar que el signo solo debe aparecer con nmeros negativos (es el valor por
defecto); un espacio en blanco para indicar que los nmeros positivos deben ir precedidos
por un espacio en blanco.

: Si aparece, los enteros que se muestran en binario, octal o hexadecimal irn precedidos
o .
por ,
: Si aparece, se usa el carcter

para sustituir los espacios en blanco.

ancho: Es un nmero entero que indica cuntos caracteres queremos que ocupe (como
mnimo) el valor representado.
precisin: nmero de decimales con que queremos representar un nmero flotante.

cdigo de tipo: carcter que indica el tipo de representacin que se desea. Es diferente
segn el tipo de datos del valor. He aqu algunos de sus posibles valores:
nmeros enteros:

carcter : en binario.
carcter : como carcter Unicode.
carcter : en base diez (es el valor por defecto).
carcter : en octal.
carcter : en hexadecimal.
carcter : igual que , pero como nmero adaptado a la cultura local (en espaol,
por ejemplo, el punto decimal se muestra como una coma).

nmeros flotantes:

carcter : notacin exponente.


carcter : notacin de punto fijo.
carcter : notacin en formato general, que solo es exponente para nmeros
grandes (es el valor por defecto).
carcter : igual que , pero como nmero adaptado a la cultura local.
carcter : muestra el nmero multiplicado por 100, en formato y seguido de
un smbolo de porcentaje.

No has de memorizar esta lista de opciones y posibles valores, pero s saber dnde est y recurrir
a ella cuando la necesites. De todos modos, la mejor manera de ver qu hace exactamente cada
opcin es estudiar ejemplos de uso.
Empecemos con algunos enteros. Imprimamos el nmero 123 en su formato por defecto en
medio de un texto:
Ahora veamos cmo afectar de modos diferentes al alineamiento, siempre con una anchura
de 10 espacios:

El

sustituye los espacios en blanco por un :

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Veamos el efecto que consigue especificar un carcter de signo:

El cdigo de tipo permite mostrar el nmero en diferentes bases o incluso como carcter
Unicode:

Con un

se muestra el prefijo que explicita la base cuando no es la decimal:

Podemos combinar los diferentes elementos y controlar con mucha precisin el formato:
No nos extenderemos tanto con las posibilidades de formato para nmeros en coma flotante,
pero no nos resistimos a poner algunos ejemplos que deberas analizar:

Acabamos indicando que hay un pequeo problema: Qu ocurre si queremos mostrar las
llaves abierta o cerrada como tales en una cadena sometida a interpolacin? Python se liar:
Las llaves que queramos mostrar como tales y que no sean objeto de sustitucin al interpolar
deben marcarse con dos apariciones seguidas de cada una de ellas:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Como ves, hemos entrado en un tema lleno de detalles. Afortunadamente no usaremos muchos
de los elementos que acabamos de presentar. Y si alguna vez te hicieran falta, siempre podrs
consultar los manuales de ayuda.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Captulo 3

Programas

Querida, realmente tengo que conseguir un lpiz ms fino! No puedo en


absoluto manejar este: escribe todo tipo de cosas, sin que yo se las dicte.
Alicia en el pas de las maravillas, Lewis Carroll

Hasta el momento hemos utilizado Python en un entorno interactivo: hemos introducido expresiones (y asignaciones a variables) y Python las ha evaluado y ha proporcionado inmediatamente
sus respectivos resultados.
Pero utilizar el sistema nicamente de este modo limita bastante nuestra capacidad de
trabajo. En este captulo aprenderemos a introducir secuencias de expresiones y asignaciones
en un fichero de texto y pedir a Python que las ejecute todas, una tras otra. Denominaremos
programa al contenido del fichero de texto1 .
Puedes crear los ficheros con cualquier editor de texto. Nosotros utilizaremos un entorno
integrado de desarrollo o IDE (por el ingls Integrated Development Environment): el entorno Eclipse con la extensin Pydev. Un entorno de programacin es un conjunto de herramientas que facilitan el trabajo del programador. Eclipse es un IDE gratuito diseado inicialmente
para desarrollar programas con Java. Ocurre que Eclipse es un entorno extensible, es decir, se
puede aadir funcionalidad y hacerlo til para cometidos distintos del original. Pydev es una
extensin de Eclipse para desarrollar programas con Python. Instalar y configurar Eclipse con
Pydev apropiadamente no es una tarea trivial.
En este captulo asumimos que dispones de un entorno Eclipse con Pydev correctamente
configurado. En principio, cada programa autnomo debera tener su propio proyecto, pero nosotros crearemos ahora un nico proyecto en el que iremos creando programas como mdulos
del mismo.

3.1.

3.1.1.

Tu primer programa

Instalar y preparar Eclipse para el trabajo con la extensin Pydev

Arranca Eclipse. Aparece un pantallazo de presentacin similar al siguiente (que es el de la


versin 4.3 de Eclipse, conocida como Kepler):

1 Tambin

se suele denominar scripts a los programas Python.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

A continuacin aparecer un cuadro de dilogo en el que se te pedir que indiques el espacio de


trabajo (workspace) en el que vas a moverte en esta sesin. El espacio de trabajo es una carpeta
(un directorio) en el que puedes agrupar proyectos relacionados entre s. Es recomendable que
uses un nico espacio de trabajo para el trabajo con este texto. Cada programa con suficiente
entidad, cuando los haya, podr crearse en su propio proyecto dentro del espacio de trabajo.
Como es la primera vez que trabajamos con Eclipse, vamos a crear un espacio de trabajo propio
al que denominaremos
. Modifica el nombre que te propone por defecto para
que quede as2 y pulsa el botn OK:

Probablemente Eclipse arranque con una pantalla como esta:

Es una pantalla de bienvenida que conduce a una serie de manuales y tutoriales. Como estos
estn principalmente orientados al trabajo con Java, no nos resultan de mucha utilidad ahora
mismo. Lo mejor es que cerremos la pestaa titulada Welcome pulsando en el aspa que hay a
su derecha. Encontrars entonces un entorno de trabajo como este:

2 La ruta del espacio de trabajo ser diferente en funcin del sistema operativo con el que ests trabajando. Las
imgenes han sido capturadas en un ordenador con sistema operativo Linux.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Hemos de instalar ahora el mdulo Pydev, que adapta Eclipse al trabajo con Python. Necesitars
una conexin a Internet y haber instalado previamente Python 3.1 (o superior). Ve al men
HelpInstall New Software. Aparecer un cuadro de dilogo como este:

Pulsa el botn Add. Aparecer un nuevo cuadro de dilogo. En el campo Name: escribe el
y en el campo Location escribe la direccin
:
texto
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Pulsa ahora el botn Ok. En la nueva pantalla que aparece, marca la casilla PyDev y
avanza dos pantallas ms pulsando Next. A continuacin, acepta las condiciones que impone
una licencia de uso, pulsa Finish e indica que confas en el certificado del sitio de instalacin
para que Eclipse proceda a instalar el componente Pydev. Por ltimo, ser necesario reiniciar
Eclipse para completar el proceso de instalacin.
Solo nos queda un paso antes de crear un proyecto Pydev: seleccionar la perspectiva Pydev.
Una perspectiva Eclipse es un conjunto de paneles dispuestos de una determinada forma que
facilitan el desarrollo con un determinado lenguaje, tipo de ficheros o plataforma. Para elegir
la perspectiva Pydev ve al men WindowOpen PerspectiveOther, selecciona Pydev en el
cuadro de dilogo que se habr abierto y pulsa OK. La apariencia de la ventana principal
cambiar un poco:

La ventana principal presenta dos regiones o vistas3 (del ingls views). En la izquierda encontrars el Pydev Package Explorer y en l aparecern los diferentes proyectos que crees
y, dentro de cada proyecto, las carpetas y ficheros que lo formen. A su derecha hay un espacio
para albergar los editores de texto con los que crears y modificars los programas.
Empecemos creando un proyecto al que llamaremos
. Selecciona la
opcin de men FileNewPydev Project. Aparecer un cuadro de dilogo como este:
3 Hay ms vistas, que puedes activar mediante WindowShow View. Por ejemplo, la vista Outline permite mostrar
una visin esquemtica del programa cuyo editor tenga el foco y te resultar muy til para navegar rpidamente por tus
programas cuando estos tengan decenas (o centenares) de lneas de cdigo.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

El nombre del proyecto (campo Project name) ser


. Dejaremos marcada
la opcin Use default para que Pydev cree la estructura del proyecto. El tipo de proyecto es
Python y la versin de la gramtica es 3.0 (aunque usemos Python 3.1). Y como este es nuestro
primer proyecto, hemos de hacer un trabajo extra: dar de alta el intrprete Python que usaremos
para ejecutar nuestro programa en el entorno. Para ello pinchamos en el enlace Please configure
an interpreter before proceeding y seleccionamos Manual Config. Esto nos llevar a un nuevo
cuadro de dilogo:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Pulsa en el botn New que hay arriba a la derecha. Aparecer un nuevo cuadro de dilogo
titulado Select interpreter. El primer campo debe contener Python34 . En un sistema Unix,
. Si ests
como Linux, el segundo campo deber contener una ruta similar a
5
:
trabajando con Microsoft Windows, el segundo campo contendr

Seguimos. Pulsamos OK y aparece un nuevo cuadro de dilogo con una relacin de rutas.
Pulsamos nuevamente OK. Regresamos as al cuadro de dilogo Preferences y en l pulsamos ahora OK. Pydev se tomar su tiempo para configurar el sistema. (Recuerda que esto
tan trabajoso solo lo hacemos una vez por espacio de trabajo, as que la prdida de tiempo no
se repetir mucho). En el cuadro de dilogo aparece, bajo el desplegable para seleccionar la
gramtica, un nuevo desplegable para seleccionar un intrprete. Podemos dejarlo tal cual est,
con la opcin Default, o seleccionar la opcin Python3 (pues en este momento solo hemos
dado de alta un intrprete y es lo mismo seleccionar Default que Python3, es decir, la
etiqueta con la que hemos nombrado dicho intrprete). Es habitual que almacenemos nuestros

4 Lo cierto es que da igual el texto del primer campo: no es ms que una etiqueta. Eso s: usemos un nombre sencillo
que deje claro que usamos un intrprete Python de la versin 3.
5 Tanto en Unix como en Windows puede haber alguna diferencia con la ruta del intrprete. Todo depende del modo
en que hiciste la instalacin del paquete Python 3. Las rutas que indicamos corresponden a instalaciones estndar de
Python 3.1.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

programas en una carpeta llamada src (del ingls source). Para ello, marcaremos la opcin
Create src folder:

Pulsamos Finish y ya estamos listos para trabajar.

Fjate en que en la vista del explorador de paquetes Python aparece una carpeta con el
. Si acercamos el ratn a ella comprobaremos que se trata de
nombre
una carpeta desplegable. Al pulsar en el botn triangular que hay a su izquierda, se desplegar
la carpeta y se mostrar su contenido:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Nos queda an un pequeo detalle para tenerlo todo listo. Nos gustara fijar una codificacin
de texto para todos los ficheros que ms tarde no nos d problemas con la representacin de los
caracteres acentuados o de la letra ee. Podemos hacer esto fichero a fichero, pero es mucho mejor
fijarlo en las preferencias del propio espacio de trabajo. Has de ir al men WindowPreferences.
Aparecer un cuadro de dilogo complejo. Selecciona la opcin GeneralWorkspace en el rbol
de mens que hay a mano izquierda. En el panel de la derecha aparecer un cuadro de dilogo
con un elemento titulado Text file encoding. Ese elemento contiene dos botones de radio con
las opciones Default y Other. Si es necesario, selecciona la opcin Other y, en el men
desplegable que se activa entonces, selecciona UTF-8. Cierra finalmente el cuadro pulsando
el botn OK:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Con eso hemos seleccionado el juego de caracteres Unicode y nuestros ficheros podrn leerse
igual en cualquier sistema moderno. Ya lo tenemos todo preparado para empezar a escribir
nuestro primer programa.

3.1.2.

Nuestro primer programa

Empezaremos por crear el fichero en el que escribiremos el programa. Pulsa el botn derecho
en la carpeta src y en el men contextual selecciona NewPydev module. En el cuadro de
dilogo no edites el primer campo, que dice
, ni el segundo, que
6
y pulsa OK. En el nuevo cuadro de dilogo
est en blanco. En el tercero escribe
que aparece, deja la seleccin de Template en la opcin Empty, tal cual est. (Seguramente
ests ya abrumado por lo trabajoso que es configurar el entorno para crear un proyecto y trabajar
en l. Tranquilo. Acabar siendo un proceso mecnico).
Acabamos de crear el fichero
y se ha abierto un editor de texto para que
podamos modificar su contenido. El fichero no est en blanco: contiene un texto que proviene de
una plantilla. El texto contiene la fecha de creacin y el nombre del autor:

Empezaremos por eliminar ese texto (ya veremos ms adelante para qu podra servir) y escribir
en su lugar este otro:
1
2
3
4

from math import pi


radio
1
permetro
2
pi
radio
permetro

Si hubisemos escrito cada una de estas lneas directamente en el intrprete interactivo


de Python, como hacamos en el captulo anterior, la ejecucin de la ltima lnea mostrara el
resultado en pantalla. Vamos a ejecutar todas las lneas del programa con una sola orden del
entorno de desarrollo: selecciona la opcin de men RunRun y elige el modo Python Run.

6 Ya habrs detectado que la palabra


est mal escrita: le falta la tilde a la i. Dado que la codificacin
de los nombres de fichero es una cuestin delicada, evitaremos el uso de caracteres que no forman parte de la tabla
ASCII, aunque ello suponga tener que cometer faltas de ortografa. Puede que esto te quite el sueo, pero de momento
no tenemos otro remedio para evitar problemas de portabilidad de los ficheros.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Punto py

Hay un convenio por el que los ficheros que contienen programas Python tienen extensin en su
nombre. La extensin de un nombre de fichero son los caracteres del mismo que suceden al (ltimo)
punto. Un fichero llamado
tiene extensin .
La idea de las extensiones viene de antiguo y es un mero convenio. Puedes prescindir de l,
pero no es conveniente. En entornos grficos (como KDE, Gnome, Max OS X o Microsoft Windows) la
extensin se utiliza para determinar qu icono va asociado al fichero y qu aplicacin debe arrancarse
para abrir el fichero al hacer clic (o doble clic) en el mismo.

No ocurre nada! Python se comporta de modo diferente en funcin de si se usa interactivamente


o ejecutando un programa escrito en un fichero. En el primer caso, cada expresin (y la ltima
lnea del programa es una expresin) provoca que se muestre por pantalla el resultado de su
evaluacin. En el segundo, es necesario decir explcitamente al intrprete que deseamos imprimir
un valor por pantalla. Para eso tenemos la funcin print:
1
2
3
4

from math import pi


radio
1
permetro
2
pi
radio
print permetro

Si ahora lo ejecutamos nuevamente, en la zona inferior aparecer una nueva vista con la
consola y, en ella, la salida del programa:

Una ltima observacin. Los programas deben ser legibles y conviene que juguemos con un elemento muy bsico: las lneas en blanco. Es buen estilo separar las diferentes zonas del programa
con lneas en blanco. En nuestro programa hay tres regiones: la importacin de elementos de
la librera matemtica, los clculos y la presentacin del resultado. El programa resulta ms
legible formateado as:
1
2
3

from math import pi


radio

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4
5
6

permetro

pi

print permetro

radio

Puede que te parezca una tontera, pero cuando tengas un programa de cientos de lneas con
algn error y hayas de leerlo una y otra vez hasta detectar ese error, agradecers todo esfuerzo
puesto en aumentar la legibilidad del programa.

32
Disea un programa que, a partir del valor del lado de un cuadrado (3 metros), muestre
el valor de su permetro (en metros) y el de su rea (en metros cuadrados).
(El permetro debe darte 12 metros y el rea 9 metros cuadrados).

33
Disea un programa que, a partir del valor de la base y de la altura de un tringulo
(3 y 5 metros, respectivamente), muestre el valor de su rea (en metros cuadrados).
Recuerda que el rea A de un tringulo se puede calcular a partir de la base b y la altura
h como A = 12 bh.
h

(El resultado es 7.5 metros cuadrados).

34
Disea un programa que, a partir del valor de los dos lados de un rectngulo (4 y 6
metros, respectivamente), muestre el valor de su permetro (en metros) y el de su rea (en metros
cuadrados).
(El permetro debe darte 20 metros y el rea 24 metros cuadrados).

3.2.

Ejecucin de programas desde la lnea de rdenes

3.3.

Entrada/salida

El programa que hemos escrito no solo puede ejecutarse desde el entorno de desarrollo. Abre
en la
un intrprete de rdenes (en Unix, cualquier terminal te vale; en Windows escribe
caja de bsqueda del icono de inicio, situado en la esquina inferior izquierda de la pantalla, y
pulsa retorno) y ve al directorio en el que se encuentra el fichero
.
y pulsa retorno de
En Unix escribe
y pulsa retorno
carro; en Windows escribe
. El sistema responder imprimiendo
de carro. A continuacin, escribe
en pantalla el resultado de ejecutar el programa.
Los programas que hemos visto en la seccin anterior adolecen de un serio inconveniente:
cada vez que quieras obtener resultados para unos datos diferentes debers editar el fichero de
texto que contiene el programa.
Por ejemplo, el siguiente programa calcula el volumen de una esfera a partir de su radio,
que es de un metro:
1
2
3
4

from math import pi


radio
1
volumen
4

pi

radio

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5
6

print volumen

El programa se ha escrito en un nuevo fichero del proyecto


. El fichero,
llamado
se ha creado pulsando el botn derecho del ratn sobre la carpeta
del
proyecto y seleccionando NewPydev module. En el cuadro de dilogo hemos escrito
en el campo
y hemos pulsado el botn Finish.
Al ejecutar el programa obtenemos en pantalla este texto:

Si deseas calcular ahora el volumen de una esfera de 3 metros de radio, debes editar el
fichero que contiene el programa, yendo a la tercera lnea y cambindola para que el programa
pase a ser este:
1
2
3
4
5
6

from math import pi


radio
3
volumen
4

print volumen

pi

radio

Al ejecutar nuevamente el programa obtenemos en pantalla este otro texto:

Y si ahora quieres calcular el volumen para otro radio, vuelta a empezar: ve a la tercera lnea,
modifica el valor del radio y ejecuta. No es el colmo de la comodidad.

3.3.1.

Lectura de datos de teclado

Vamos a aprender a hacer que nuestro programa, cuando se ejecute, pida el valor del radio
para el que vamos a efectuar los clculos sin necesidad de editar el fichero de programa.
Hay una funcin predefinida, input (en ingls significa entrada), que hace lo siguiente:
detiene la ejecucin del programa y espera a que el usuario escriba un texto (el valor del radio,
por ejemplo) y pulse la tecla de retorno de carro; en ese momento prosigue la ejecucin y la
funcin devuelve una cadena con el texto que tecle el usuario.
Si deseas que el radio sea un valor flotante, debes transformar la cadena devuelta por input
en un dato de tipo flotante llamando a la funcin float. La funcin float recibir como argumento
la cadena que devuelve input y proporcionar un nmero en coma flotante. (Recuerda, para
cuando lo necesites, que existe otra funcin de conversin, int, que devuelve un entero en lugar
de un flotante). Por otra parte, input es una funcin y, por tanto, el uso de los parntesis que
siguen a su nombre es obligatorio, incluso cuando no tenga argumentos.
anterior para que quede de la siguiente forma:
Modificamos el fichero
1
2
3
4
5
6
7
8

from math import pi

cadena_leda
input
radio
float cadena_leda
volumen

print volumen

pi

radio

Ejecuta ahora el programa. Si ests en el entorno de desarrollo Eclipse/Pydev, pincha en


la vista de la consola y teclea el valor del radio. Escribe, por ejemplo, el valor 2. Pulsa a
continuacin el retorno de carro y en la misma vista de consola aparecer el volumen. Este es
el resultado de la ejecucin, donde el texto que teclea el usuario aparece en un color distinto y
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

va seguido de la marca de retorno de carro (para recordarte que debes pulsarlo tras introducir
el dato):
El programa no es muy elegante por el modo en que pide el dato de entrada: la consola se
queda bloqueada y no sale ningn mensaje que alerte al usuario de que se le pide un dato en
particular. La funcin input admite un argumento opcional: una cadena con el texto que debe
mostrarse en pantalla para que el usuario sepa qu introducir. Esta otra versin del programa
es ms elegante:
1
2
3
4
5
6
7
8

from math import pi

cadena_leda
input
radio
float cadena_leda
volumen

print volumen

pi

radio

El usuario ver ahora un mensaje de texto Dame el radio: e introducir el valor del radio
como respuesta a esta peticin. Volvamos a ejecutar el programa introduciendo el valor 2 como
radio.
Mucho mejor!
Para acabar, ten en cuenta que es posible juntar en una sola las dos lneas dedicadas a la
lectura del dato:
1
2
3
4
5
6
7

from math import pi


radio

volumen

float input
4

print volumen

pi

radio

35
Disea un programa que pida el valor del lado de un cuadrado y muestre el valor de
su permetro y el de su rea. (Prueba que tu programa funciona correctamente con este ejemplo:
si el lado vale 1.1, el permetro ser 4.4, y el rea 1.21).

36
Disea un programa que pida el valor de los dos lados de un rectngulo y muestre
el valor de su permetro y el de su rea. (Prueba que tu programa funciona correctamente con
este ejemplo: si un lado mide 1 y el otro 5, el permetro ser 12.0, y el rea 5.0).

37
Disea un programa que pida el valor de la base y la altura de un tringulo y muestre
el valor de su rea. (Prueba que tu programa funciona correctamente con este ejemplo: si la base
es 10 y la altura 100, el rea ser 500.0).

38
Disea un programa que pida el valor de los tres lados de un tringulo y calcule
el valor de su rea y permetro. Recuerda que
 el rea A de un tringulo puede calcularse a
partir de sus tres lados, a, b y c, as: A = s(s a)(s b)(s c), donde s = (a + b + c)/2.
(Prueba que tu programa funciona correctamente con este ejemplo: si los lados miden 3, 5 y 7,
el permetro ser 15.0 y el rea 6.49519052838).
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

3.3.2.

Ms sobre la funcin print

Las cadenas pueden usarse tambin para mostrar textos por pantalla en cualquier momento
a travs de sentencias print.
1
2
3
4
5
6
7
8
9

10

from math import pi


print

radio

volumen
print
print

float input
4

pi

radio

volumen

La primera aparicin de print muestra en pantalla un mensaje que informa al usuario del
propsito del programa. La segunda aparicin de print muestra dos cosas en pantalla: el texto
Volumen:, el valor del volumen de la esfera y las unidades en las que se expresa el volumen.
La funcin print puede mostrar en una misma lnea ms de un valor: los valores que se desee
mostrar van entre parntesis y separados por comas. Finalmente, la ltima aparicin de print
hace que se muestre un texto de agradecimiento y despedida.
Cuando ejecutes este programa, fjate en que las cadenas que se muestran con print no
aparecen entrecomilladas. El usuario del programa no est interesado en saber que le estamos
mostrando datos del tipo cadena: solo le interesa el texto de dichas cadenas. Mucho mejor, pues,
no mostrarle las comillas:

39
El rea A de un tringulo se puede calcular a partir del valor de dos de sus lados, a y
b, y del ngulo que estos forman entre s con la frmula A = 12 ab sin(). Disea un programa
que pida al usuario el valor de los dos lados (en metros), el ngulo que estos forman (en grados),
y muestre el valor del rea.
b

(Ten en cuenta que la funcin sin de Python trabaja en radianes, as que el ngulo que leas en
grados debers pasarlo a radianes sabiendo que radianes son 180 grados. Prueba que has
hecho bien el programa introduciendo los siguientes datos: a = 1, b = 2, = 30; el resultado
es 0.5).

40
Haz un programa que pida al usuario una cantidad de euros, una tasa de inters
y un nmero de aos. Muestra por pantalla en cunto se habr convertido el capital inicial
transcurridos esos aos si cada ao se aplica la tasa de inters introducida.
Recuerda que un capital de C euros a un inters del x por cien durante n aos se convierten
en C (1 + x/100)n euros. (Prueba tu programa sabiendo que una cantidad de 10,000 al 4.5 %
de inters anual se convierte en 24,117.14 al cabo de 20 aos).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

41
Haz un programa que pida el nombre de una persona y lo muestre en pantalla
repetido 1000 veces, pero dejando un espacio de separacin entre aparicin y aparicin del
nombre. (Utiliza los operadores de concatenacin y repeticin).

Por lo visto hasta el momento, cada print empieza a imprimir en una nueva lnea. Esto es
porque cada print aade al final un carcter especial: un terminador de lnea. Podemos evitarlo
si indicamos que no hay terminador de lnea. Fjate en este programa:
1
2
3
4
5
6
7
8
9

10

from math import pi


print

radio

volumen
print
print

float input
4

pi

radio

volumen

end

La penltima lnea contiene un print con un argumento especial: end


. El mensaje de
agradecimiento se mostrar ahora en la misma lnea que el resultado del clculo. Y una sutileza:
para evitar
hemos aadido un espacio en blanco tras el punto en la cadena
que la siguiente lnea se imprimiera pegada a ese punto. Este es el resultado de una ejecucin
del programa:
Es el momento de recordar que podemos formatear una cadena para mostrar el resultado del
clculo:
1
2
3
4
5
6
7
8
9

10

from math import pi


print

radio

volumen
print
print

3.4.

float input
4

pi

radio

format volumen

end

Sobre la legibilidad de los programas

Hemos visto cmo un uso apropiado de las lneas en blanco ayuda a hacer ms legibles los
programas. Vale la pena que abundemos en la cuestin de la legibilidad. Los programadores
pasan muchas horas leyendo programas escritos por ellos mismos o por otros. Las razones son
varias:
Puede que hayas de seguir trabajando en un proyecto que abandonaste hace tiempo. Eso
supone que releas lo que escribiste para continuar.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

O puede que un programa que ya habas dado por bueno se revele defectuoso unos das
o meses despus de ser utilizado a diario, con lo que debers releer tu programa y buscar
los errores cometidos para corregirlos.
O tambin es posible que un programa ya escrito y sin defectos deba extenderse para que
se le aada nueva funcionalidad o se adapte a nuevos estndares. Nuevamente te tocar
releer buena parte del cdigo para introducir los cambios necesarios.

O quiz hayas conseguido trabajo en una empresa y te asignen la mejora de una pieza de
cdigo que escribi otro programador. Cuanda hayas de estudiarlo, le estars infinitamente
agradecido si se preocup de la legibilidad.
O podra ser el caso de que estuvieses escribiendo programas para demostrar al profesorado que has alcanzado los objetivos de una asignatura de aprendizaje de la programacin.
Seguro que te gustar ver al evaluador contento cuando lea tus programas y sea capaz
de entenderlos.

En todos estos casos (y en muchos otros), haberse asegurado de facilitar la lectura del cdigo
ser un elemento con un claro impacto en la productividad.

3.4.1.

Algunos convenios

Comparemos dos programas que hacen lo mismo desde el punto de vista de la legibilidad.
Este es el primer programa:
1
2
3
4
5
6

1
2
3
4
5
6
7
8
9

10

h
float input
v
float input
z
h
v
print
v
2
h
v
print

Y este es el segundo:

format z
format v

print

altura
float input
anchura
float input
rea
altura
permetro
2
print
print

anchura
altura
2

anchura

format permetro
format rea

Basta con leer este segundo programa para saber qu hace. Evidentemente, el programa
pide la altura y la anchura de un rectngulo y calcula su permetro y rea, valores que muestra
a continuacin. Son muchos los elementos que han ayudado a hacer ms legible el segundo
programa:

usa nombres arbitrarios y breves para las variables, mientras que el prograutiliza identificadores representativos y tan largos como sea necesario. El
ma
pensaba ms en teclear poco que en hacer comprensible el
programador de
usa una misma variable, v, para dos propsitos distintos:
programa. Adems,
albergar primero una anchura y, despus, un permetro.
En su lugar,

no tiene una estructura clara: mezcla clculos con impresin de resultados.


diferencia claramente zonas distintas del programa (lectura

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

de datos, realizacin de clculos y visualizacin de resultados) y llega a usar marcas


visuales como las lneas en blanco para separarlas. Probablemente el programador de
escriba el programa conforme se le iban ocurriendo cosas. El programador
tena claro qu iba a hacer desde el principio: planific la estructura del
de
programa.
utiliza frmulas poco frecuentes para realizar algunos de los clculos: la forutilima en que calcula el permetro es vlida, pero poco ortodoxa. Por contra,
za formas de expresin de los clculos que son estndar. El programador de
debera haber pensado en los convenios a la hora de utilizar frmulas.

Los mensajes de
, tanto al pedir datos como al mostrar resultados, son de
psima calidad. Un usuario que se enfrenta al programa por primera vez tendr serios
problemas para entender qu se le pide y qu se le muestra como resultado. El programa
emplea mensajes de entrada/salida muy informativos. Seguro que el
pensaba que l sera el nico usuario de su programa.
programador de

Atenerte a las reglas usadas en

ser fundamental para hacer legibles tus programas.

42
Disea un programa legible que solicite el radio de una circunferencia y muestre su
rea y permetro con solo 2 decimales.

3.4.2.

Comentarios

Dentro de poco empezaremos a realizar programas de mayor envergadura y con mucha


mayor complicacin. Incluso observando las reglas indicadas, va a resultar una tarea ardua leer
un programa completo.
Un modo de aumentar la legibilidad de un programa consiste en intercalar comentarios que
expliquen su finalidad o que aclaren sus pasajes ms oscuros.
Como esos comentarios solo tienen por objeto facilitar la legibilidad de los programas para
los programadores, pueden escribirse en el idioma que desees. Cuando el intrprete Python ve
un comentario no hace nada con l: lo omite. Cmo le indicamos al intrprete que cierto texto
es un comentario? Necesitamos alguna marca especial. Los comentarios Python se inician con el
smbolo (que se lee almohadilla): todo texto desde la almohadilla hasta el final de la lnea
se considera comentario y, en consecuencia, es omitido por Python.
He aqu un programa con comentarios:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16

Programa: rectangulo.py
Propsito: Calcula el permetro y el rea de un rectngulo a partir de su altura y anchura.
Autor: John Cleese
Fecha: 1/1/2010

Peticin de los datos (en metros)


altura
float input
anchura
float input

Clculo del rea y del permetro


rea
altura
anchura
permetro
2
altura
2
anchura
Impresin de resultados por pantalla
print
print

format permetro
format rea

solo dos decimales.

en la cabecera del programa, comentando el nombre del programa, su propsito, el autor


y la fecha;
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

al principio de cada una de las grandes zonas del programa, indicando qu se hace en
ellas;

y al final de una de las lneas (la penltima), para comentar alguna peculiaridad de la
misma.

Es buena prctica que comentes tus programas. Pero ten presente que no hay reglas fijas que
indiquen cundo, dnde y cmo comentar los programas: las que acabes adoptando formarn
parte de tu estilo de programacin.

3.5.

Grficos de tortuga

Todos los programas que te hemos presentado utilizan el teclado y la pantalla en modo
texto para interactuar con el usuario. Sin embargo, ests acostumbrado a interactuar con el
ordenador mediante un terminal grfico y usando, adems del teclado, el ratn.
Python trae de serie una librera para la implementacin de interfaces grficas de usuario,
esto es, ofrece a travs de una librera la capacidad de crear ventanas, poblarlas con mens,
botones, cajas de texto, etctera, y definir el comportamiento de estos elementos al interactuar
con el usuario. La librera se llama Tkinter. Es pronto para que nos enfrentemos a ella. En
este libro nos limitaremos a crear aplicaciones grficas muy sencillas con una tortuga. Una
tortuga? El nombre de este tipo de grficos tiene su historia y te damos algunas pinceladas en
el cuadro Logo y la tortuga.
Logo y la tortuga

Ha habido varios intentos de disear lenguajes que faciliten a los nios el aprendizaje de la
programacin. Seymour Papert y Wally Feurzeig disearon, a mediados de los aos 60 del siglo XX,
un lenguaje de programacin muy sencillo que tena ese objetivo. El lenguaje se denomina Logo y,
ya entonces, tena una fuerte orientacin a los grficos. Los sistemas informticos de la poca an
eran mastodnticos y su precio los haca asequibles casi exclusivamente para grandes empresas y
universidades. Pensar en ensear a programar a los nios era toda una osada.
Un elemento esencial de Logo era la posibilidad de confeccionar dibujos con un plotter virtual.
Se poda controlar un lpiz al que dar rdenes del estilo avanza 100 pasos, gira 45 grados a
la derecha, levanta el lpiz, avanza 10 pasos, baja el lpiz y avanza 100 pasos. El lpiz se
representaba con un tringulo issceles acutngulo con el vrtice ms agudo orientado en la direccin
del movimiento. Para hacer ms atractivo el sistema, se denomin tortuga al tringulo. De ah que a
los sistemas grficos inspirados en la idea de Logo se les denomine genricamente sistemas grficos
de tortuga.

Imagina una tortuga que lleva un lpiz en la boca (?) y est esperando nuestras rdenes
para dibujar sobre un gran papel extendido en el suelo. Le podemos dar rdenes sencillas, del
tipo apoya el lpiz en el papel, avanza 100 pasos, gira 10 grados a la derecha, levanta el
lpiz. Tan pronto recibe una orden, la tortuga la ejecuta. Si el lpiz est apoyado en la superficie,
avanzar 100 pasos supone hacer una lnea de esa longitud en la direccin hacia la que miraba
la tortuga, dejando a la tortuga en una nueva posicin. Si el lpiz no est apoyado, avanzar
esos 100 pasos no tendr un efecto visible sobre el papel, pero habr desplazado igualmente a
la tortuga en la direccin hacia la que miraba.
Escribamos un programa que haga avanzar 100 pasos a la tortuga y deje un trazo en pantalla.
El programa tendr cuatro partes:
Primero se importarn los elementos necesarios del mdulo turtle.
Luego crearemos una pantalla a la que daremos un tamao.

Despus crearemos una tortuga y le diremos que avance 100 pasos.

Y finalmente detendremos el programa hasta que el usuario pulse el botn del ratn en la
superficie de dibujo.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

He aqu el programa:
1
2
3
4
5
6
7
8
9

10

from turtle import Screen

Turtle

pantalla
Screen
pantalla setup 425 225
pantalla screensize 400 200
tortuga
Turtle
tortuga forward 100
pantalla exitonclick

Antes de ejecutarlo, veamos cmo hemos codificado cada una de las cuatro partes. Primero
hemos importado los elementos Screen y Turtle definidos en la librera turtle con la sentencia from turtle import Screen Turtle. A continuacin, hemos creado una pantalla (en ingls,
screen) y la hemos almacenado en la variable pantalla. Las dos siguientes lneas han fijado la
dimensin de la pantalla. La primera de ellas invoca al mtodo setup de pantalla, que fija el ancho (425 pxeles) y alto (225 pxeles) de la ventana. La segunda invoca al mtodo screensize, que
fija el tamao de la superficie de dibujo (400 pxeles de ancho y 200 de alto). Puedes observar
que la ventana es algo ms grande que la superficie de dibujo (unos 25 pxeles adicionales en
cada dimensin): es porque la ventana contiene algunos elementos decorativos que necesitan su
propio espacio. Despus hemos creado una tortuga (en ingls, turtle) y hemos almacenado una
referencia a ella en la variable tortuga. La siguiente sentencia ejecuta sobre tortuga el mtodo
forward con el argumento 100. Le estamos dando una orden a la tortuga: que avance 100 pasos
(forward, en ingls, significa adelante) en la direccin en la que mira, que por defecto es
hacia la derecha (o, si lo prefieres considerar en trminos de puntos cardinales, hacia el este).
La ltima sentencia contiene una llamada a un mtodo de pantalla que evita que la ventana en
la que se dibuja desaparezca inmediatamente: el mtodo exitonclick fuerza a esperar a que el
usuario haga clic en la ventana.
Ya podemos ejecutar el programa. En pantalla aparecer esto:

El tringulo es la tortuga y la lnea es el rastro que ha dejado al desplazarse. Pulsa en el


interior de la ventana para que se cierre y finalice la ejecucin del programa.
El mtodo left hace que la tortuga gire hacia la izquierda tantos grados como se indique en
el nico argumento del mtodo. Si combinamos forward y left podemos dibujar un cuadrado con
unas pocas rdenes:
1
2
3
4
5
6
7
8
9

10
11
12

from turtle import Screen

Turtle

pantalla
Screen
pantalla setup 425 225
pantalla screensize 400 200
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga

Turtle
forward 100
left 90
forward 100
left 90
forward 100

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

13
14
15
16

tortuga left 90
tortuga forward 100
pantalla exitonclick

Adems de left, que gira hacia la izquierda, tienes el mtodo right, que gira hacia la derecha.
El lpiz puede levantarse para hacer que no deje rastro. Si no se pudiera, todos los dibujos
estaran hechos con un solo trazo. El mtodo penup, sin argumentos, levanta el lpiz, y el mtodo
pendown, tambin sin argumentos, lo vuelve a apoyar en la superficie de dibujo. Usamos ambos
mtodos para dibujar dos cuadrados no conectados:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

from turtle import Screen

Turtle

pantalla
Screen
pantalla setup 425 225
pantalla screensize 400 200
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga

Turtle
forward
left 90
forward
left 90
forward
left 90
forward

tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga

forward
left 90
forward
left 90
forward
left 90
forward

tortuga
tortuga
tortuga
tortuga

100
100
100
100

penup
right 90
forward 100
pendown
100
100
100
100

pantalla exitonclick

Este es el resultado:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Sabes qu orden ha generado cada uno de los lados de ambos cuadrados? Fjate en que el
dibujo se hace a una velocidad ralentizada y es fcil ver cmo se va ejecutando cada orden.
Aqu relacionamos los mtodos bsicos de dibujo con la tortuga. Estn todos los que ya
hemos presentado y alguno ms:
forward d : Avanza d pasos.

backward d : Retrocede d pasos.

left g : Gira a la izquierda g grados.

right g : Gira a la derecha g grados.


penup
43

: Levanta el lpiz.

pendown

: Baja el lpiz.

Disea un programa que dibuje un tringulo equiltero con la tortuga.

44
Disea un programa que dibuje un cuadrado cuyo lado mida 200 pasos y otro cuadrado
de lado 100 centrado en su interior.

Podemos controlar algunos elementos del aspecto de las lneas, como el grosor del trazo y
el color:
pensize s : Usa un lpiz con trazo de s pxeles de grosor.

pencolor c : Usa el color c para los trazos, donde c es una cadena con el nombre del
,
,
,
,
color en ingls. Algunas cadenas de color vlidas son
,
,
,
,
y
.

Practica con los siguientes ejercicios.

45
Disea un programa que dibuje un tringulo equiltero con la tortuga. El trazo del
tringulo debe tener un grosor de 10 pxeles.

46
Disea un programa que dibuje un cuadrado cuyo lado mida 200 pasos y otro cuadrado
de lado 100 centrado en su interior. El cuadrado exterior ha de ser de color rojo y el interior de
color azul.

Los mtodos forward, backward, left y right permiten controlar a la tortuga con coordenadas
y ngulos relativos a la posicin y orientacin de la tortuga. Si decimos dos veces forward 10 ,
la tortuga habr avanzado 20 pasos desde la posicin de partida en la direccin a la que apunta.
Si apunta al norte y damos dos rdenes consecutivas left 90 , la tortuga apuntar al sur. En
ocasiones querremos dar rdenes con coordenadas y ngulos absolutos. Estos otros mtodos
permiten controlar a la tortuga con valores absolutos:
goto x

y : Ubica a la tortuga en la posicin de coordenadas (x, y).

setx x : Ubica a la tortuga en la posicin de abcisa x y la misma ordenada actual.

sety y : Ubica a la tortuga en la posicin de ordenada y y la misma abcisa actual.

setheading g : Hace que la tortuga apunte en direccin g grados (donde 0 grados es la


direccin este).
towards x y : Hace que la tortuga apunte en direccin al punto (x, y).
home

: Ubica a la tortuga en la posicin de coordenadas (0, 0).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

47
Disea un programa que dibuje un tringulo equiltero con la tortuga. No uses los
mtodos left o right.

48
Disea un programa que dibuje un cuadrado cuyo lado mida 200 pasos y otro cuadrado
de lado 100 centrado en su interior. No uses los mtodos left o right.
Hay un par de utilidades de la tortuga que nos darn un poco de juego: dot y circle.
dot d : Dibuja un punto de dimetro d centrado en la posicin actual.

circle r : Dibuja un crculo de radio r. El crculo est centrado a r pasos a la izquierda


de la tortuga.
write t : Escribe el texto de la cadena t en pantalla, en la posicin actual de la tortuga.

Adems, podemos establecer el sistema de coordenadas de la pantalla con el mtodo setworldcoordinates:

setworldcoordinates x1 y1 x2 y2 : Establece el sistema de coordenadas de la pantalla, donde (x1, y1) representa el vrtice inferior izquierdo y (x2, y2) el vrtice superior
derecho.

Pongamos en prctica mucho de lo aprendido:


1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

from turtle import Screen

Turtle

pantalla
Screen
pantalla setup 425 425
pantalla screensize 400 400
pantalla setworldcoordinates 50
tortuga

Turtle

tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga

pensize
dot 10
forward
dot 10
forward
dot 10
forward
dot 10

tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga

pencolor
pensize 5
circle 20
forward 50
pensize 4
left 20
circle 20
forward 50
pensize 3
left 20
circle 20
forward 50
pensize 2
left 20
circle 20

150

350

250

100
100
100

tortuga penup
tortuga goto 0 100
tortuga pendown

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

tortuga
tortuga
tortuga
tortuga
tortuga

forward 50
pensize 1
left 20
circle 20
forward 50

tortuga penup
tortuga goto 0
100
tortuga towards 0 0
tortuga write
tortuga backward 20
tortuga write
pantalla exitonclick

Este es el resultado:

Detengmonos a hacer una observacin: el programa est repleto de fragmentos que se repiten
una y otra vez. Fjate en la zona en la que se dibuja la lnea con puntos. Es una sucesin de
fragmentos de la forma:
1
2

tortuga dot 10
tortuga forward 100

Y la zona en la que se dibujan los crculos es poco ms que una sucesin de grupos de lneas
como este:
1
2
3
4

tortuga
tortuga
tortuga
tortuga

pensize x
left 20
circle 20
forward 50

(donde x va tomando valores decrecientes de 5 a 1). Ha de haber modos de hacer que los
programas sean ms compactos. Tranquilo: los hay. Ya llegaremos.
Por otra parte, habrs comprobado que el dibujo aparece lentamente aunque tu ordenador
sea potente y vemos a la tortuga ir desplazndose casi punto a punto por la pantalla. Con
razn la llaman tortuga! Ese efecto es deliberado y puedes evitarlo. El mtodo speed permite
controlar la velocidad con la que se desplaza la tortuga: su argumento es un nmero entre 0 y 10,
donde 1 es la mnima velocidad y 10 es la mxima. . . siempre que desees que el movimiento de
la tortuga no sea instantneo. Si quieres que sea instantneo, fija la velocidad al valor 0. Has
de saber que la velocidad por defecto es 6. Las velocidades ms lentas pueden venir bien para
entender qu est ocurriendo cuando el programa no hace lo que uno cree que debiera hacer.
Vamos a hacer un primer programa con salida grfica y que presente cierta utilidad: un
programa que muestra el porcentaje de suspensos, aprobados, notables y sobresalientes de una
asignatura mediante un grfico de pastel. He aqu un ejemplo de grfico como el que deseamos
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

para una tasa de suspensos del 10%, un 20% de aprobados, un 40% de notables y un 30% de
sobresalientes:
aprobados
notables

suspensos

sobresalientes

Disearemos nuestro programa paso a paso. Empezaremos por crear el crculo.


1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

from turtle import Screen


radio

300

tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga

penup
goto 0
radio
pendown
circle radio
penup
home
pendown

Turtle

pantalla
Screen
tortuga
Turtle
tortuga speed 0

pantalla exitonclick

Hemos empezado bajando el cursor radio unidades para dibujar a continuacin un crculo.
Como el crculo se dibuja a mano izquierda de la tortuga y esta mira hacia el este, el crculo se
dibujar justo encima. La tortuga vuelve al punto original con tortuga home . Observa cmo
hemos levantado y bajado el lpiz a conveniencia para asegurarnos de que solo se dibuja el
crculo, y no cada uno de los movimientos de la tortuga. El radio se ha parametrizado almacenando
su valor en una variable. Si ms adelante deseamos cambiar el tamao del crculo, ser fcil:
bastar con cambiar el valor de una sola variable.
Ahora vamos a asignar un porcentaje a cada una de las calificaciones. Por cierto: aadir
unos comentarios mejorar la legibilidad del programa.
1
2
3
4
5
6
7
8
9

10
11
12
13
14

from turtle import Screen


Calificaciones
suspensos
10
aprobados
20
notables
40
sobresalientes
30

Turtle

Radio del crculo


radio
300
Inicializacin
pantalla
Screen
tortuga
Turtle

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

15
16
17
18
19
20
21
22
23
24
25
26
27

tortuga speed 0

Dibujo del crculo exterior.


tortuga penup
tortuga goto 0
radio
tortuga pendown
tortuga circle radio
tortuga penup
tortuga home
tortuga pendown

Salir cuando se pulse el botn en la ventana.


pantalla exitonclick

Para dibujar cada lnea divisoria entre porciones de la tarta tenemos que calcular el ngulo
correspondiente. Y repetir el proceso para cada porcin de la tarta:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

from turtle import Screen


Calificaciones
suspensos
10
aprobados
20
notables
40
sobresalientes
30

Turtle

Radio del crculo


radio
300
Inicializacin
pantalla
Screen
tortuga
Turtle
tortuga speed 0

Dibujo del crculo exterior.


tortuga penup
tortuga goto 0
radio
tortuga pendown
tortuga circle radio
tortuga penup
tortuga home
tortuga pendown

Dibujo de la lnea para los suspensos.


ngulo
360
suspensos
100
tortuga left ngulo
tortuga forward radio
tortuga backward radio
Escribir el texto para los suspensos.
tortuga penup
tortuga right ngulo
2
tortuga forward radio
2
tortuga write
tortuga backward radio
2
tortuga left ngulo
2
tortuga pendown

Dibujo de la lnea para los aprobados.


ngulo
360
aprobados
100
tortuga left ngulo

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

tortuga forward radio


tortuga backward radio

Escribir el texto para los aprobados.


tortuga penup
tortuga right ngulo
2
tortuga forward radio
2
tortuga write
tortuga backward radio
2
tortuga left ngulo
2
tortuga pendown

Dibujo de la lnea para los notables.


ngulo
360
notables
100
tortuga left ngulo
tortuga forward radio
tortuga backward radio
Escribir el texto para los notables.
tortuga penup
tortuga right ngulo
2
tortuga forward radio
2
tortuga write
tortuga backward radio
2
tortuga left ngulo
2
tortuga pendown

Dibujo de la lnea para los sobresalientes.


ngulo
360
sobresalientes
100
tortuga left ngulo
tortuga forward radio
tortuga backward radio
Escribir el texto para los sobresalientes.
tortuga penup
tortuga right ngulo
2
tortuga forward radio
2
tortuga write
tortuga backward radio
2
tortuga left ngulo
2
tortuga pendown

Salir cuando se pulse el botn en la ventana.


pantalla exitonclick

Analiza bien cada uno de los bloques que componen el programa. Este es el resultado de la
ejecucin:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Mmmm. Casi perfecto. Lo nico que no queda bien es que la tortuga se queda en la pantalla y
ensucia el resultado. Esto nos da pie para presentar dos mtodos ms:
hideturtle

showturtle

: Esconde la tortuga.

: Muestra la tortuga.

Con esta informacin, modifica t mismo el programa para que desaparezca la tortuga al final.

49
Modifica el programa para que sea el usuario quien proporcione, mediante el teclado,
el valor del porcentaje de suspensos, aprobados, notables y sobresalientes.
50
Modifica el programa para que sea el usuario quien proporcione, mediante el teclado,
el nmero de suspensos, aprobados, notables y sobresalientes. (Antes de dibujar el grfico de
pastel debes convertir esas cantidades en porcentajes).

51
Queremos representar la informacin de forma diferente: mediante un grfico de barras.
He aqu cmo:
40 %

30 %
20 %
10 %

suspensos

aprobados

notables

sobresalientes

Disea un programa que solicite por teclado el nmero de personas con cada una de las
cuatro calificaciones y muestre el resultado con un grfico de barras.

Y antes de acabar, abundemos en la observacin que hicimos antes: nuestro ltimo programa
consta de una serie de bloques bsicamente idnticos. Cada una de las cuatro porciones repite
una serie de rdenes en las que apenas cambia un valor numrico y una cadena. Ya veremos
cmo reducir este programa usando funciones y estructuras de control. Empezaremos por las
estructuras de control.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Captulo 4

Estructuras de control

De ah que estn dando vueltas continuamente, supongo dijo Alicia.


Si, as es dijo el Sombrerero, conforme se van ensuciando las cosas.
Pero qu ocurre cuando vuelven al principio de nuevo? se atrevi a preguntar Alicia.

Alicia en el pas de las maravillas, Lewis Carroll

Los programas que hemos aprendido a construir hasta el momento presentan siempre una
misma secuencia de acciones:
1) Se piden datos al usuario (asignando a variables valores obtenidos con input).

2) Se efectan clculos con los datos introducidos por el usuario, guardando el resultado en
variables (mediante asignaciones).
3) Se muestran por pantalla los resultados almacenados en variables (mediante la funcin print).

Estos programas se forman como una serie de lneas que se ejecutan una tras otra, desde la
primera hasta la ltima y siguiendo el mismo orden con el que aparecen en el fichero: el flujo
de ejecucin del programa es estrictamente secuencial.
No obstante, es posible alterar el flujo de ejecucin de los programas para hacer que:

tomen decisiones a partir de los datos y/o resultados intermedios y, en funcin de estas,
ejecuten ciertas sentencias y otras no;
tomen decisiones a partir de los datos y/o resultados intermedios y, en funcin de estas,
ejecuten ciertas sentencias ms de una vez.

El primer tipo de alteracin del flujo de control se efecta con sentencias condicionales o de
seleccin y el segundo tipo con sentencias iterativas o de repeticin. Las sentencias que permiten
alterar el flujo de ejecucin se engloban en las denominadas estructuras de control de flujo (que
abreviamos con el trmino estructuras de control).
Estudiaremos una forma adicional de alterar el flujo de control que permite sealar, detectar
y tratar los errores que se producen al ejecutar un programa: las sentencias de emisin y captura
de excepciones.

4.1.

4.1.1.

Sentencias condicionales

Un programa ilustrativo: resolucin de ecuaciones de primer grado

Veamos un ejemplo. Diseemos un programa para resolver cualquier ecuacin de primer


grado de la forma
ax + b = 0,
donde x es la incgnita.
Antes de empezar hemos de responder a dos preguntas:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1) Cules son los datos del problema? (Generalmente, los datos del problema se pedirn al
usuario con input).
En nuestro problema, los coeficientes a y b son los datos del problema.

2) Qu deseamos calcular? (Tpicamente, acabaremos mostrando al usuario su valor mediante


una llamada a print).
Obviamente, el valor de x.

Ahora que conocemos los datos de entrada y el resultado que hemos de calcular, es decir, los
datos de salida, nos preguntamos: cmo calculamos la salida a partir de la entrada? En nuestro
ejemplo, despejando x de la ecuacin llegamos a la conclusin de que x se obtiene calculando
b/a.
Siguiendo el esquema de los programas que sabemos hacer, procederemos as:
1) Pediremos el valor de a y el valor de b (que supondremos de tipo flotante).
2) Calcularemos el valor de x como b/a.

3) Mostraremos por pantalla el valor de x.

Empecemos creando un nuevo proyecto Pydev al que denominaremos


crearemos un nuevo mdulo llamado
:
1
2
3
4
5
6
7
8

print
a
b
x

. En su carpeta

float input
float input
b

print

Las lneas se ejecutan en el mismo orden con el que aparecen en el programa. Vemoslo
funcionar:

52
grado:
E
1
2
3
4
5
6
7
8

print
a
b
a

print

Un programador propone el siguiente programa para resolver la ecuacin de primer


float input
float input
x

Es correcto este programa? Si no, explica qu est mal.

E
1
2

53

print

Otro programador propone este programa:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

3
4
5
6
7
8

a
b

print

float input
float input

Es correcto? Si no lo es, explica qu est mal.

Nuestro programa presenta un punto dbil: cuando a vale 0, se produce un error de divisin
por cero:

Hemos de evitar los errores en tiempo de ejecucin: detienen abruptamente la ejecucin del
programa y muestran mensajes de error poco comprensibles para el usuario del programa. Si al
escribir el programa hemos previsto una solucin para todo posible error de ejecucin, podemos
(y debemos) tomar el control de la situacin en todo momento. Y si no lo hemos hecho, somos
unos malos programadores1 .
Errores de ejecucin

Hemos dicho que conviene evitar los errores de programa que se producen en tiempo de ejecucin
y, ciertamente, la industria de desarrollo de software realiza un gran esfuerzo para que sus productos
estn libres de errores de ejecucin. No obstante, el gran tamao de los programas y su complejidad
(unidos a las prisas por sacar los productos al mercado) hacen que muchos de estos errores acaben
haciendo acto de presencia. Todos hemos sufrido la experiencia de, ejecutando una aplicacin, obtener
un mensaje de error indicando que se ha abortado la ejecucin del programa o, peor an, el computador
se ha quedado colgado. Si la aplicacin contena datos de trabajo importantes y no los habamos
guardado en disco, estos se habrn perdido irremisiblemente. Nada hay ms irritante para el usuario
que una aplicacin poco estable, es decir, propensa a la comisin de errores en tiempo de ejecucin.
El sistema operativo es, tambin, software, y est sujeto a los mismos problemas de desarrollo de
software que las aplicaciones convencionales. Sin embargo, los errores en el sistema operativo son,
por regla general, ms graves, pues suelen ser estos los que dejan colgado al ordenador.
El famoso sal y vuelve a entrar en la aplicacin o reinicia el computador que suele proponerse
como solucin prctica a muchos problemas de estos es consecuencia de los bajos niveles de calidad
de buena parte del software que se comercializa.

4.1.2.

La sentencia condicional if

En nuestro programa de ejemplo nos gustara detectar si a vale cero para, en ese caso, no
, que es la que provoca el error. Cmo
ejecutar el clculo de la sexta lnea de
hacer que cierta parte del programa se ejecute o deje de hacerlo en funcin de una condicin
determinada?
Los lenguajes de programacin convencionales presentan una sentencia especial cuyo significado es:
Al llegar a este punto, ejecuta esta(s) accin(es) solo si esta condicin es cierta.

1 Aunque lo cierto es que programar es una tarea muy ardua y resulta muy difcil pensar en todo aquello que podra
ir mal y anticiparse. Muchos errores de programacin no se descubren hasta bien tarde. Seguro que, desgraciadamente,
te ha tocado sufrirlo como usuario en ms de un programa.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Este tipo de sentencia se denomina condicional o de seleccin y en Python es de la siguiente


forma:
1
2
3
4
5

if condicin
accin
accin
accin

(En ingls if significa si). Las acciones, que sern sentencias Python vlidas, se escriben
con un sangrado mayor que el de la lnea que contiene la condicin. Estas acciones solo se
ejecutan si la condicin proporciona como resultado el valor booleano True.
En nuestro caso, deseamos detectar la condicin a no vale 0 y, solo en ese caso, ejecutar
las ltimas lneas del programa:
1
2
3
4
5
6
7

print
a
b

if a

float input
float input

0
x
b
print

Analicemos detenidamente las lneas 6, 7 y 8. En la lnea 6 aparece la palabra reservada if


seguida de lo que, segn hemos dicho, debe ser una condicin. La condicin se lee fcilmente
significa es distinto de. As pues, la lnea 6 se lee si a es distinto de 0.
si sabemos que
La lnea que empieza con if debe finalizar obligatoriamente con dos puntos ( ). Fjate en que
las dos siguientes lneas se escriben ms a la derecha2 . Decimos que estas lneas presentan
mayor sangrado o indentacin que la lnea que empieza con if. Este mayor sangrado indica que
0: solo cuando
la ejecucin de estas dos lneas depende de que se satisfaga la condicin a
esta es cierta se ejecutan las lneas de mayor sangrado. As pues, cuando a valga 0, esas lneas
no se ejecutarn, evitando de este modo el error de divisin por cero.
Veamos qu ocurre ahora si volvemos a introducir los datos que antes provocaron el error:
Mmmm. . . no ocurre nada. No se produce un error, es cierto, pero el programa acaba sin
proporcionar ninguna informacin. Analicemos la causa. Las cinco primeras lneas del programa
se han ejecutado (imprime un mensaje y nos pide los valores de a y b); tambin se ha ejecutado
la sexta lnea, pero dado que la condicin no se ha cumplido (a vale 0), las lneas 7 y 8 se han
ignorado y, como no hay ms lneas en el programa, la ejecucin ha finalizado sin ms. No se
ha producido un error, ciertamente, pero acabar as la ejecucin del programa puede resultar un
tanto confuso para el usuario.
Veamos qu hace este otro programa:
1
2
3
4
5
6
7

8
9

print
a
b

if a

float input
float input

0
x
b
print

2 Para

destacar esta caracterstica, hemos dibujado una lnea vertical que marca el nivel al que apareci el if.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

10
11

if a

0
print

La lnea 10 contiene, nuevamente, una sentencia condicional que afecta a la lnea 11 (observa
que est ms sangrada). En lugar de , el operador de comparacin utilizado ahora es . La
sentencia se lee si a es igual a 0.
La ejecucin con los mismos datos de antes es, ahora, un poco ms clara:
Ante datos tales que a es distinto de 0, el programa resuelve la ecuacin:
Estudiemos con detenimiento qu ha pasado en cada uno de los casos:
a=0yb=3
Las lneas 1, 3 y 4 se ejecutan, con lo que se
imprime un mensaje y se leen los valores de a
y b.
...........................................
La lnea 6 se ejecuta y el resultado de la comparacin es falso.
...........................................
Las lneas 7 y 8 se ignoran.
...........................................
La lnea 10 se ejecuta y el resultado de la
comparacin es cierto.
...........................................
La lnea 11 se ejecuta y se muestra por
pantalla el mensaje

a = 1 y b = 1
Las lneas 1, 3 y 4 se ejecutan, con lo que se
imprime un mensaje y se leen los valores de a
y b.
...........................................
La lnea 6 se ejecuta y el resultado de la comparacin es cierto.
...........................................
Se ejecutan las lneas 7 y 8, con lo que se
muestra por pantalla el valor de la Solucin:
.
...........................................
La lnea 10 se ejecuta y el resultado de la
comparacin es falso.
...........................................
La lnea 11 se ignora.

Este tipo de anlisis, en el que seguimos el curso del programa lnea a lnea para una
configuracin dada de los datos de entrada, recibe el nombre de traza de ejecucin. Las trazas
de ejecucin son de gran ayuda para comprender qu hace un programa y localizar as posibles
errores.
1
2
3
4
5
6
7
8
9

10
11

54

print
a
b

if a
if a

Un estudiante ha tecleado el ltimo programa as:

float input
float input

0
x
b
print
0
print

Al ejecutarlo obtiene este error:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Por ms que el estudiante lee el programa, no encuentra fallo alguno. l dice que la lnea 10,
la marcada como errnea, se lee as: si a es igual a cero. . . . Est en lo cierto? Por qu se
detecta un error?
55

1
2
3
4
5
6
7
8
9

10

print
a
b

if a

Un programador primerizo cree que la lnea 10 de la ltima versin del programa


es innecesaria, as que propone esta otra versin como solucin vlida:

float input
float input

0
x
b
print

print

Haz una traza del programa para a = 2 y b = 2. Son correctos todos los mensajes que
muestra por pantalla el programa?

4.1.3.

Sentencias condicionales anidadas

Vamos a realizar un ltimo refinamiento del programa. De momento, cuando a es 0 el programa muestra un mensaje que indica que la ecuacin no tiene solucin. Nosotros sabemos que
esto no es cierto: si, adems, b vale 0, entonces la ecuacin tiene infinitas soluciones. Para que
el programa d una informacin correcta vamos a modificarlo de modo que, cuando a sea 0,
muestre un mensaje u otro en funcin del valor de b:
1
2
3
4
5
6
7
8
9

10
11
12
13
14

print
a
b

if a
if a

float input
float input

0
x
b
print
if b

0
print
if b
0
print

Fjate en el sangrado de las lneas. Las lneas 1114 estn ms a la derecha que la lnea 10.
Ninguna de ellas se ejecutar a menos que la condicin de la lnea 10 se satisfaga. Ms an, la
lnea 11 est ms a la derecha que la lnea 10, por lo que su ejecucin depende del resultado
de la condicin de dicha lnea; y la ejecucin de la lnea 12 depende de la satisfaccin de la
condicin de la lnea 11. Recuerda que en los programas Python el sangrado determina de qu
sentencia depende cada bloque de sentencias.
Pues bien, acabamos de presentar una nueva idea muy potente: las estructuras de control
pueden anidarse, es decir, aparecer unas dentro de otras. Esto no ha hecho ms que empezar.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

56
Indica qu lneas del ltimo programa (y en qu orden) se ejecutarn para cada uno
de los siguientes casos:
1) a = 2 y b = 6.

2) a = 0 y b = 3.

3) a = 0 y b = 3.
4) a = 0 y b = 0.

57
Disea un programa que lea un nmero flotante por teclado y muestre por pantalla
solo si el nmero es menor que cero.
el mensaje
58
Disea un programa que lea un nmero flotante por teclado y muestre por pantalla
solo si el nmero es mayor o igual que cero.
el mensaje

59
Disea un programa que lea la edad de dos personas y diga quin es ms joven, la
primera o la segunda. Ten en cuenta que ambas pueden tener la misma edad. En tal caso, hazlo
saber con un mensaje adecuado.

60
Disea un programa que lea un carcter de teclado y muestre por pantalla el mensaje
Es parntesis solo si el carcter ledo es un parntesis abierto o cerrado.

61
Indica en cada uno de los siguientes programas qu valores en las respectivas entradas
provocan la aparicin de los distintos mensajes. Piensa primero la solucin y comprueba luego
que es correcta ayudndote con el ordenador.
1)

1
2
3
4
5
6

2)

1
2
3
4
5
6
7
8
9

10
11
12
13

1
2

62

letra

input

if letra
print
if letra
print

from math import floor


grados

float input

cuadrante
floor grados
if cuadrante
0
print
if cuadrante
1
print
if cuadrante
2
print
if cuadrante
3
print

La funcin floor redondea hacia abajo.


360

90

Qu mostrar por pantalla el siguiente programa?

if 14
120
print

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

3
4

if

print

Por lo visto hasta el momento, podemos comparar valores numricos con valores numricos y
cadenas con cadenas. Tanto los valores numricos como las cadenas pueden ser el resultado de
una expresin que aparezca explcitamente en la propia comparacin. Por ejemplo, para saber si
el producto de dos nmeros enteros es igual a 100, podemos utilizar este programa:
1
2
3
4
5
6
7

n
m

if n

int input
int input

m
print
if n
m
print

63

100
100

format n

format n

Disea un programa que, dado un nmero entero, muestre por pantalla el mensaje
cuando el nmero sea par y el mensaje
cuando

sea impar.
(Una pista: un nmero es par si el resto de dividirlo por 2 es 0, e impar en caso contrario).

64
Disea un programa que, dado un nmero entero, determine si este es el doble de un
nmero impar. (Ejemplo: 14 es el doble de 7, que es impar).

65
Disea un programa que, dados dos nmeros enteros, muestre por pantalla uno
,
de estos mensajes:
o bien
, dependiendo de la verificacin de la condicin correspondiente al significado de
cada mensaje.

66
Un capital de C euros a un inters del x por cien anual durante n aos se convierte
en C (1 + x/100)n euros. Disea un programa Python que solicite la cantidad C , el inters x y
el nmero de aos n y calcule el capital final solo si x es una cantidad positiva.

67
Realiza un programa que calcule el desglose mnimo en billetes y monedas de una
cantidad exacta de euros. Hay billetes de 500, 200, 100, 50, 20, 10 y 5 y monedas de 2 y 1 .
Por ejemplo, si deseamos conocer el desglose de 434 , el programa mostrar por pantalla
el siguiente resultado:

(Que cmo se efecta el desglose mnimo? Muy fcil. Empieza por calcular la divisin entera
entre la cantidad y 500 (el valor de la mayor moneda): 434 entre 500 da 0, as que no hay billetes
de 500 en el desglose; divide a continuacin la cantidad 434 entre 200, cabe a 2 y sobran 34,
as que en el desglose hay 2 billetes de 200 ; dividimos a continuacin 34 entre 100 y vemos
que no hay ningn billete de 100 en el desglose (cabe a 0); como el resto de la ltima divisin
es 34, pasamos a dividir 34 entre 20 y vemos que el desglose incluye un billete de 20 y an
nos faltan 14 por desglosar. . . ).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4.1.4.

Otro ejemplo: resolucin de ecuaciones de segundo grado

Para afianzar los conceptos presentados (y aprender alguno nuevo), vamos a presentar otro
ejemplo. En esta ocasin vamos a resolver ecuaciones de segundo grado, que son de la forma
ax 2 + bx + c = 0.

Cules son los datos del problema? Los coeficientes a, b y c. Qu deseamos calcular? Los
valores de x que hacen cierta la ecuacin. Dichos valores son:
x1 =

b +

b2 4ac
2a

Un programa directo para este clculo es:


1
2
3
4
5
6
7
8
9

10
11
12

from math import sqrt


print
a
b
c

x1
x2

print

float input
float input
float input
b
b

sqrt b 2
sqrt b 2

x2 =

b2 4ac
.
2a

La funcin sqrt calcula la raz cuadrada de un nmero.

4 a c
4 a c

2
2

a
a

format x1

Ejecutemos el programa:

x2

Un problema evidente de nuestro programa es la divisin por cero que tiene lugar cuando a
vale 0 (pues entonces el denominador, 2a, es nulo). Tratemos de evitar el problema de la divisin
por cero del mismo modo que antes, pero mostrando un mensaje distinto, pues cuando a vale 0
la ecuacin no es de segundo grado, sino de primer grado.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15

from math import sqrt


print
a
b
c

if a
if a

float input
float input
float input

0
x1
x2
print
0
print

b
b

La funcin sqrt calcula la raz cuadrada de un nmero.

sqrt b 2
sqrt b 2

4 a c
4 a c

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

2
2

a
a

format x1

x2

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4.1.5.

En caso contrario (else)

Fjate en que tanto en el ejemplo que estamos desarrollando ahora como en el anterior,
hemos recurrido a sentencias condicionales que conducen a ejecutar una accin si se cumple
una condicin y a ejecutar otra si esa misma condicin no se cumple:
1
2
3
4

if condicin
acciones
if condicin contraria
otras acciones

Este tipo de combinacin es muy frecuente, hasta el punto de que se ha incorporado al


lenguaje de programacin una forma abreviada que significa lo mismo:
1
2
3
4

if condicin
acciones
else
otras acciones

La palabra else significa, en ingls, si no o en caso contrario. Es muy importante que


respetes el sangrado: las acciones siempre un poco a la derecha, y el if y el else, alineados en
la misma columna.
1
2
3
4
5
6
7
8
9

10
11
12
13
14

from math import sqrt


print
a
b
c

if a
else

float input
float input
float input

0
x1
x2
print
print

b
b

La funcin sqrt calcula la raz cuadrada de un nmero.

sqrt b 2
sqrt b 2

4 a c
4 a c

2
2

a
a

format x1

x2

El programa no acaba de estar bien. Es verdad que cuando a vale 0, la ecuacin es de primer
grado, pero, aunque sabemos resolverla, no lo estamos haciendo. Sera mucho mejor si, en ese
caso, el programa nos ofreciera la solucin:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15

from math import sqrt


print
a
b
c

if a
else

float input
float input
float input

0
x1
x2
print

x
c
print

b
b

La funcin sqrt calcula la raz cuadrada de un nmero.

sqrt b 2
sqrt b 2

4 a c
4 a c

2
2
format x

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

a
a

format x1

x2

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Mmmm. . . an hay un problema: Qu pasa si a vale 0 y b tambin vale 0? La secuencia de


lneas que se ejecutar ser: 1, 3, 5, 6, 7, 9 y 14. De la lnea 14 no pasar porque se producir
una divisin por cero.

Cmo evitar este nuevo error? Muy sencillo, aadiendo nuevos controles con la sentencia if,
tal y como hicimos para resolver correctamente una ecuacin de primer grado:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15

from math import sqrt


print
a
b
c

if a
else

16

float input
float input
float input

0
x1
x2
print
if b

else

17
18
19
20
21

b
b

0
x
c
print
if c

else

La funcin sqrt calcula la raz cuadrada de un nmero.

sqrt b 2
sqrt b 2

0
print

4 a c
4 a c

2
2

a
a

format x1

x2

format x

print

Es muy importante que te fijes en que las lneas 1421 presentan un sangrado tal que todas
ellas dependen del else de la lnea 13. Las lneas 15 y 16 dependen del if de la lnea 14, y las
lneas 1821 dependen del else de la lnea 17. Estudia bien el programa: aparecen sentencias
condicionales anidadas en otras sentencias condicionales que, a su vez, estn anidadas. Complicado? No tanto. Los principios que aplicamos son siempre los mismos. Si analizas el programa
y lo estudias por partes, vers que no es tan difcil de entender. Pero quiz lo verdaderamente
difcil no sea entender programas con bastantes niveles de anidamiento, sino disearlos.
1
2
3
4
5
6
7
8
9

10
11
12
13

68

Hay alguna diferencia entre el programa anterior y este otro cuando los ejecutamos?

from math import sqrt


print
a
b
c

if a

La funcin sqrt calcula la raz cuadrada de un nmero.

float input
float input
float input

if b

if c

else

0
print

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

14
15
16
17
18
19
20

else

21

1
2
3
4
5
6
7
8
9

10
11
12
13

69

else

print

x
c
print

x1
x2
print

b
b

sqrt b 2
sqrt b 2

print

if a

else

14
15
16
17
18
19
20
21

2
2

a
a

format x1

x2

Hay alguna diferencia entre el programa anterior y este otro cuando los ejecutamos?

from math import sqrt


a
b
c

4 a c
4 a c

format x

float input
float input
float input

0 and b
print
if a

else

0 and b
print
if a

else

0
x
c
print
x1
x2
print

La funcin sqrt calcula la raz cuadrada de un nmero.

0 and c

b
b

sqrt b 2
sqrt b 2

4 a c
4 a c

format x
2
2

a
a

format x1

x2

70
Disea un programa Python que lea un carcter cualquiera desde el teclado, y muestre
cuando el carcter sea una letra mayscula y el mensaje
el mensaje
cuando sea una minscula. En cualquier otro caso, no mostrar mensaje alguno.
(Considera nicamente letras del alfabeto ingls). Pista: aunque parezca una obviedad, recuerda
que una letra es minscula si est entre la
y la
, y mayscula si est entre la
y la
.
71
Ampla la solucin al ejercicio anterior para que cuando el carcter introducido no
. (Nota: no te preocupes por las letras
sea una letra muestre el mensaje
ee, ce cedilla, vocales acentuadas, etc.).

72
Ampla el programa del ejercicio anterior para que pueda identificar las letras ee
minscula y mayscula.

73
Modifica el programa que propusiste como solucin al ejercicio 65 sustituyendo todas
las condiciones que sea posible por clusulas else de condiciones anteriores.

4.1.6.

Una estrategia de diseo: refinamientos sucesivos

Es lgico que cuando ests aprendiendo a programar te cueste gran esfuerzo construir mentalmente un programa tan complicado, pero posiblemente sea porque sigues una aproximacin
equivocada: no debes intentar construir mentalmente todo el programa de una vez. Es recomendable que sigas una estrategia similar a la que hemos usado al desarrollar los programas de
ejemplo:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1) Primero haz una versin sobre papel que resuelva el problema de forma directa y, posiblemente, un tanto tosca. Una buena estrategia es plantearse uno mismo el problema con unos
datos concretos, resolverlo a mano con lpiz y papel y hacer un esquema con el orden de las
operaciones realizadas y las decisiones tomadas. Tu primer programa puede pedir los datos
de entrada (con input), hacer los clculos del mismo modo que t los hiciste sobre el papel
(utilizando variables para los resultados intermedios, si fuera menester) y mostrar finalmente
el resultado del clculo (con print).

2) Analiza tu programa y considera si realmente resuelve el problema planteado: es posible


que se cometan errores en tiempo de ejecucin?, hay configuraciones de los datos que son
especiales y, para ellas, el clculo debe ser diferente?
3) Cada vez que te plantees una de estas preguntas y tengas una respuesta, modifica el programa
en consecuencia. No hagas ms de un cambio cada vez.
4) Si el programa ya funciona correctamente para todas las entradas posibles y eres capaz de
anticiparte a los posibles errores de ejecucin, enhorabuena!, ya casi has terminado. En caso
contrario, vuelve al paso 2.

5) Ahora que ya ests seguro de que todo funciona correctamente, teclea el programa en
el ordenador y efecta el mayor nmero de pruebas posibles, comprobando cuidadosamente
que el resultado calculado es correcto. Presta especial atencin a configuraciones extremas o
singulares de los datos (los que pueden provocar divisiones por cero o valores muy grandes,
o muy pequeos, o negativos, etc.). Si el programa calcula algo diferente de lo esperado o si
se aborta la ejecucin del programa por los errores detectados, vuelve al paso 2.
Pruebas unitarias

Correr una batera de pruebas manualmente cada vez que cambias algo de un programa, bien
porque sigues una aproximacin de refinamientos sucesivos, bien porque ests corrigiendo errores
detectados tardamente, es una labor ardua y aburridsima. Probablemente empezars a encontrar
todo tipo de excusas y justificaciones para no pasar tu batera de pruebas tras cada cambio.
Para evitar que la pereza pueda con las buenas prcticas, hay herramientas que permiten construir
pruebas cuya ejecucin es automtica. Tras cada ejecucin se muestra un informe con las pruebas que
fallaron y la razn de que fallaran. Algunas de estas herramientas cuentan con una interfaz grfica
que muestra una luz verde si todas las pruebas se ejecutaron sin detectar fallo alguno, y roja si alguna
fall.
La pruebas automticas que testean pequeas unidades funcionales, como los programas que
estamos escribiendo por el momento, se denominan pruebas unitarias (del ingls unit tests).

Nadie es capaz de hacer un programa suficientemente largo de una sentada, empezando a


escribir por la primera lnea y acabando por la ltima, una tras otra, del mismo modo que nadie
es capaz de escribir una novela o una sinfona de una sentada3 . Lo normal es empezar con un
borrador e ir refinndolo, mejorndolo poco a poco.
Un error frecuente es tratar de disear el programa directamente sobre el ordenador, escribindolo a bote pronto. Es ms, hay estudiantes que se atreven a empezar con la escritura de
un programa sin haber entendido bien el enunciado del problema que se pretende resolver. Es
fcil pillarlos en falta: no saben resolver a mano un caso particular del problema. Una buena
prctica, pues, es solucionar manualmente unos pocos ejemplos concretos para estar seguros de
que conocemos bien lo que se nos pide y cmo calcularlo. Una vez superada esta fase, estars
en condiciones de elaborar un borrador con los pasos que has de seguir. Crenos: es mejor que
pienses un rato y disees un borrador del algoritmo sobre papel. Cuando ests muy seguro de
la validez del algoritmo, implemntalo en Python y prubalo sobre el ordenador. Las pruebas
con el ordenador te ayudarn a encontrar errores.
Ciertamente es posible utilizar el ordenador directamente, como si fuera el papel. Nada
impide que el primer borrador lo hagas ya en pantalla, pero, si lo haces, vers que:
3 Aunque hay excepciones: cuenta la leyenda que Mozart escriba sus obras de principio a fin, sin volver atrs para
efectuar correcciones.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Los detalles del lenguaje de programacin interferirn en el diseo del algoritmo (he
de poner dos puntos al final de la lnea?, uso marcas de formato para imprimir los
resultados?, etc.): cuando piensas en el mtodo de resolucin del problema es mejor
hacerlo con cierto grado de abstraccin, sin tener en cuenta todas las particularidades de
la notacin.
Si ya has tecleado un programa y sigue una aproximacin incorrecta, te resultar ms
molesto prescindir de l que si no lo has tecleado an. Esta molestia conduce a la tentacin
de ir poniendo parches a tu deficiente programa para ver si se puede arreglar algo. El
resultado ser, muy probablemente, un programa ilegible, psimamente organizado. . . y
errneo. Te costar la mitad de tiempo empezar de cero, pero esta vez haciendo bien las
cosas: pensando antes de escribir nada.
El sndrome A m nunca se me hubiera ocurrido esto

Programar es una actividad que requiere un gran esfuerzo intelectual, no cabe duda, pero sobre
todo, ahora que empiezas, es una actividad radicalmente diferente de cualquier otra para la que te
vienes preparando desde la enseanza primaria. Llevas muchos aos aprendiendo lengua, matemticas,
fsica, etc., pero nunca antes habas programado. Los programas que hemos visto en este captulo te
deben parecer muy complicados, cuando no lo son tanto.
La reaccin de muchos estudiantes al ver la solucin que da el profesor o el libro de texto a
un problema de programacin es decirse a m nunca se me hubiera ocurrido esto. Debes tener en
cuenta dos factores:

La solucin final muchas veces esconde la lnea de razonamiento que permiti llegar a ese programa concreto. Nadie construye los programas de golpe: por regla general se hacen siguiendo
refinamientos sucesivos a partir de una primera versin bastante tosca.

La solucin que se te presenta sigue la lnea de razonamiento de una persona concreta: el


profesor. Puede que tu lnea de razonamiento sea diferente y, sin embargo, igualmente vlida
(o incluso mejor!), as que tu programa puede no parecerse en nada al suyo y, a la vez, ser
correcto. No obstante, te conviene estudiar la solucin que te propone el profesor: la lectura
de programas escritos por otras personas es un buen mtodo de aprendizaje y, probablemente,
la solucin que te ofrece resuelva cuestiones en las que no habas reparado (aunque solo sea
porque el profesor lleva ms aos que t en esto de programar).

4.1.7.

Un nuevo refinamiento del programa de ejemplo

Parece que nuestro programa ya funciona correctamente. Probemos a resolver esta ecuacin:
x 2 + 2x + 3 = 0

Nuevamente un error! El mensaje de error es diferente de los anteriores y es un error de


dominio matemtico.
El problema es que estamos intentando calcular la raz cuadrada de un nmero negativo en
la lnea 10. El resultado es un nmero complejo, pero el mdulo math no sabe de nmeros
complejos, as que sqrt falla y se produce un error. Tambin en la lnea 11 se tiene que calcular
la raz cuadrada de un nmero negativo, pero como la lnea 10 se ejecuta en primer lugar, es
ah donde se produce el error y se aborta la ejecucin. La lnea 11 no llega a ejecutarse.
Podemos controlar este error asegurndonos de que el trmino b2 4ac (que recibe el nombre
de discriminante) sea mayor o igual que cero antes de calcular la raz cuadrada:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4
5
6
7
8
9

10
11

from math import sqrt


print
a
b
c

if a

12
13
14
15
16
17
18

else

19

float input
float input
float input

if b

else
if b

else

20
21
22
23
24

La funcin sqrt calcula la raz cuadrada de un nmero.

2
4 a c
0
x1
b
sqrt b 2
x2
b
sqrt b 2
print
print

0
x
c
print
if c

else

0
print

4 a c
4 a c

2
2

a
a

format x1

x2

format x

print

74
Un programador ha intentado solucionar el problema del discriminante negativo con
un programa que empieza as:
1
2
3
4
5
6
7
8
9

10
11
12
13

from math import sqrt


print
a
b
c

if a

float input
float input
float input

0
if sqrt b
x1
x2

2
4 a c
0
b
sqrt b 2
4 a c
b
sqrt b 2
4 a c

2
2

a
a

Evidentemente, el programa es incorrecto y te sorprender saber que algunos estudiantes


proponen soluciones similares a esta. El problema estriba en el posible valor negativo del
argumento de sqrt, as que la comparacin es incorrecta, pues pregunta por el signo de la raz
de dicho argumento. Pero el programa no llega siquiera a dar solucin alguna (bien o mal
calculada) cuando lo ejecutamos con, por ejemplo, a = 4, b = 2 y c = 4. Qu sale por pantalla
en ese caso? Por qu?
Dado que solo hemos usado sentencias condicionales para controlar los errores, es posible
que te hayas llevado la impresin de que esta es su nica utilidad. En absoluto. Vamos a utilizar
una sentencia condicional con otro propsito. Mira qu ocurre cuando tratamos de resolver la
ecuacin x 2 2x + 1 = 0:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Las dos soluciones son iguales, y queda un tanto extrao que el programa muestre el mismo
valor dos veces. Hagamos que, cuando las dos soluciones sean iguales, solo se muestre una de
ellas:
1
2
3
4
5
6
7
8
9

10
11

from math import sqrt


print
a
b
c

if a

12

float input
float input
float input

if b

13
14
15
16
17
18
19
20
21

else

22

else
if b

else

23
24
25
26
27

4.1.8.

La funcin sqrt calcula la raz cuadrada de un nmero.

2
4 a c
0
x1
b
sqrt b 2
x2
b
sqrt b 2
if x1
x2
print
else
print
print

0
x
c
print
if c

else

0
print

4 a c
4 a c

2
2

a
a

format x1

format x1

x2

format x

print

Otro ejemplo: mximo de una serie de nmeros

Ahora que sabemos utilizar sentencias condicionales, vamos con un problema sencillo, pero
que es todo un clsico en el aprendizaje de la programacin: el clculo del mximo de una serie
de nmeros.
Empezaremos por pedirle al usuario dos nmeros enteros y le mostraremos por pantalla cul
es el mayor de los dos.
Estudia esta solucin, a ver qu te parece:
1
2
3
4
5
6
7
8
9

a
b

if a

else

int input
int input

b
mximo
mximo

print

a
b

mximo

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Optimizacin

Podemos plantear un nuevo refinamiento que tiene por objeto hacer un programa ms rpido, ms
eficiente. Fjate en que en las lneas 10, 11 y 12 del ltimo programa se calcula cada vez la expresin
b 2
4 a c. Para qu hacer tres veces un mismo clculo? Si las tres veces el resultado va a ser
el mismo, no es una prdida de tiempo repetir el clculo? Podemos efectuar una sola vez el clculo
y guardar el resultado en una variable.
1
2
3
4
5
6
7
8
9

10
11
12

from math import sqrt


print
a
b
c

if a

13
14
15
16
17
18
19
20
21
22
23

else

24
25
26
27
28

La funcin sqrt calcula la raz cuadrada de un nmero.

float input
float input
float input

0
discriminante
b 2
4 a c
if discriminante
0
x1
b
sqrt discriminante
x2
b
sqrt discriminante
if x1
x2
print
else
print
else
print
if b

else

0
x
c
print
if c

else

0
print

2
2

a
a

format x1

format x1

x2

format x

print

Hacer que un programa funcione ms eficientemente es optimizar el programa. No te obsesiones


ahora con la optimizacin: ests aprendiendo a programar. Asegrate de que tus programas funcionan
correctamente, que ya habr tiempo para optimizar.

75
Qu lneas del ltimo programa se ejecutan y qu resultado aparece por pantalla en
cada uno de estos casos?
1) a = 2 y b = 3.

2) a = 3 y b = 2.

3) a = 2 y b = 0.
4) a = 1 y b = 1.

Analiza con cuidado el ltimo caso. Observa que los dos nmeros son iguales. Cul es, pues, el
mximo? Es correcto el resultado del programa?

76
Un aprendiz de programador ha diseado este otro programa para calcular el mximo
de dos nmeros:
1
2
3
4
5

a
b

if a

int input
int input

b
mximo

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6
7
8
9

if b

a
mximo

print

mximo

Es correcto? Qu pasa si introducimos dos nmeros iguales?

Vamos con un problema ms complicado: el clculo del mximo de tres nmeros enteros (que
llamaremos a, b y c). He aqu una estrategia posible:

1) Me pregunto si a es mayor que b y, si es as, de momento a es candidato a ser el mayor, pero


no s si lo ser definitivamente hasta compararlo con c. Me pregunto, pues, si a es mayor
que c.
1) Si a tambin es mayor que c, est claro que a es el mayor de los tres.
2) Y si no, c es el mayor de los tres.

2) Pero si no es as, es decir, si a es menor o igual que b, el nmero b es, de momento, mi


candidato a nmero mayor. Falta compararlo con c.
1) Si tambin es mayor que c, entonces b es el mayor.
2) Y si no, entonces c es el mayor.

Ahora que hemos diseado el procedimiento, construyamos un programa Python que implemente
ese algoritmo:
1
2
3
4
5
6
7
8
9

10
11
12

a
b
c

if a
else

13
14
15
16

int input
int input
int input

b
if a
c
mximo
else
mximo
if b

else

print

77
casos?

c
mximo
mximo

a
c

b
c

mximo

Qu secuencia de lneas de este ltimo programa se ejecutar en cada uno de estos

1) a = 2, b = 3 y c = 4.

2) a = 3, b = 2 y c = 4.

3) a = 1, b = 1 y c = 1.

Puede que la solucin que hemos propuesto te parezca extraa y que t hayas diseado un
programa muy diferente. Es normal. No existe un nico programa para solucionar un problema
determinado y cada persona desarrolla un estilo propio en el diseo de los programas. Si el que
se propone como solucin no es igual al tuyo, el tuyo no tiene por qu ser errneo; quiz solo
sea distinto. Por ejemplo, este otro programa tambin calcula el mximo de tres nmeros, y es
muy diferente del que hemos propuesto antes:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4
5
6
7
8
9

10
11
12

a
b
c

int input
int input
int input

candidato
a
if b
candidato
candidato
b
if c
candidato
candidato
c
mximo
candidato
print

mximo

78
Disea un programa que calcule el mximo de 5 nmeros enteros. Si sigues una
estrategia similar a la de la primera solucin propuesta para el problema del mximo de 3
nmeros, tendrs problemas. Intenta resolverlo como en el ltimo programa de ejemplo, es decir,
con un candidato a valor mximo que se va actualizando al compararse con cada nmero.

79
Disea un programa que calcule la menor de cinco palabras dadas; es decir, la primera
palabra de las cinco en orden alfabtico. Aceptaremos que las maysculas son alfabticamente
menores que las minsculas, de acuerdo con la tabla ASCII.

80
Disea un programa que calcule la menor de cinco palabras dadas; es decir, la
primera palabra de las cinco en orden alfabtico. No aceptaremos que las maysculas sean
es menor que
.
alfabticamente menores que las minsculas. O sea,
81
Disea un programa que, dados cinco nmeros enteros, determine cul de los cuatro
ltimos nmeros es ms cercano al primero. (Por ejemplo, si el usuario introduce los nmeros 2,
6, 4, 1 y 10, el programa responder que el nmero ms cercano al 2 es el 1).

82
Disea un programa que, dados cinco puntos en el plano, determine cul de los
cuatro ltimos puntos es ms cercano al primero. Un punto se representar con dos variables:
una
 para la abcisa y otra para la ordenada. La distancia entre dos puntos (x1 , y1 ) y (x2 , y2 ) es
(x1 x2 )2 + (y1 y2 )2 .

Las condiciones pueden incluir cualquier expresin cuyo resultado sea interpretable en trminos de cierto o falso. Podemos incluir, pues, expresiones lgicas tan complicadas como deseemos.
Fjate en el siguiente programa, que sigue una aproximacin diferente para resolver el problema
del clculo del mximo de tres nmeros:
1
2
3
4
5
6
7
8
9

10
11
12

a
b
c

if a

int input
int input
int input

b and a
mximo
a
if b
a and b
mximo
b
if c
a and c
mximo
c
print

mximo

La expresin a
b and a
mayor o igual que c.

c, por ejemplo, se lee a es mayor o igual que b y a es

83
Indica en cada uno de los siguientes programas qu valores o rangos de valores
provocan la aparicin de los distintos mensajes:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1)

1
2
3
4
5
6
7

da

if 0

else

8
9

2)

1
2
3
4
5
6
7

mes

if 1

else

8
9

10
11
12
13
14
15

3)

1
2
3
4
5
6
7

car
if

else

8
9

10

4)

1
2
3
4
5
6

ao

int input

da
print

15

if da
32
print
else
print

int input

mes
print

format da

if mes
4 or mes
5 or mes
print
else
if not mes
7 or 9
mes
print
else
if not mes
10 and mes
print
else
print
input

print

car lower

if not car
print
print
else
print

int input

if ao
4
print
else
print

0 and

or

ao

or

100

11 and

mes

12

format mes

car

car

end

0 or ao
400
format ao

format ao

84
La frmula C  = C (1 + x/100)n nos permite obtener el capital final que lograremos
a partir de un capital inicial (C ), una tasa de inters anual (x) en tanto por cien y un nmero
de aos (n). Si lo que nos interesa conocer es el nmero de aos n que tardaremos en lograr
un capital final C  partiendo de un capital inicial C a una tasa de inters anual x, podemos
despejar n en la frmula de la siguiente manera:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

log(C  ) log(C )
log(1 + x/100)
Disea un programa Python que obtenga el nmero de aos que se tarda en conseguir un
capital final dado a partir de un capital inicial y una tasa de inters anual tambin dados. El
programa debe tener en cuenta cundo se puede realizar el clculo y cundo no en funcin
del valor de la tasa de inters (para evitar una divisin por cero, el clculo de logaritmos de
valores negativos, etc.). . . con una excepcin: si C y C  son iguales, el nmero de aos es 0
independientemente de la tasa de inters (incluso de la que provocara una divisin por cero).
(Ejemplos: Para obtener 11,000 con una inversin de 10,000 al 5% anual es necesario
esperar 1.9535 aos. Obtener 11,000 con una inversin de 10,000 al 0% anual es imposible.
Para obtener 10,000 con una inversin de 10,000 no hay que esperar nada, sea cual sea el
inters).
n=

85
Disea un programa que, dado un nmero real que debe representar la calificacin
numrica de un examen, proporcione la calificacin cualitativa correspondiente al nmero dado.
La calificacin cualitativa ser una de las siguientes: Suspenso (nota menor que 5), Aprobado
(nota mayor o igual que 5, pero menor que 7), Notable (nota mayor o igual que 7, pero menor
que 9), Sobresaliente (nota mayor o igual que 9, pero menor que 10), Matrcula de Honor
(nota 10).

86
Disea un programa que, dado un carcter cualquiera, lo identifique como vocal minscula, vocal mayscula, consonante minscula, consonante mayscula u otro tipo de carcter.
(Considera nicamente letras del alfabeto ingls).

4.1.9.
1
2

Evaluacin con cortocircuitos

La evaluacin de expresiones lgicas tiene algo especial. Observa la condicin de este if:

if a

0 or 1 a

Puede provocar una divisin por cero? No, nunca. Observa que si a vale cero, el primer
trmino del or es True. Como la evaluacin de una o lgica de True con cualquier otro valor,
True o False, es necesariamente True, Python no evala el segundo trmino y se ahorra as un
esfuerzo innecesario.
Algo similar ocurre en este otro caso:
1
2

if a

0 and 1 a

Si a es nulo, el valor de a
0 es falso, as que ya no se procede a evaluar la segunda
parte de la expresin.
Al calcular el resultado de una expresin lgica, Python evala (siguiendo las reglas de asociatividad y precedencia oportunas) lo justo hasta conocer el resultado: cuando el primer trmino
de un or es cierto, Python acaba y devuelve directamente cierto y cuando el primer trmino de
un and es falso, Python acaba y devuelve directamente falso. Este modo de evaluacin se conoce
como evaluacin con cortocircuitos.

87
Por qu obtenemos un error en la siguiente sesin de trabajo con el intrprete
interactivo?

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

De Morgan

Las expresiones lgicas pueden resultar complicadas, pero es que los programas hacen, en ocasiones, comprobaciones complicadas. Tal vez las ms difciles de entender son las que comportan
algn tipo de negacin, pues generalmente nos resulta ms difcil razonar en sentido negativo que
afirmativo. A los que empiezan a programar les lan muy frecuentemente las negaciones combinadas
con or o and. Veamos algn ejemplo de juguete. Supn que para aprobar una asignatura hay que
obtener ms de un 5 en dos exmenes parciales, y que la nota de cada uno de ellos est disponible
en las variables parcial1 y parcial2, respectivamente. Estas lneas de programa muestran el mensaje
Has suspendido. cuando no has obtenido al menos un 5 en los dos exmenes:
1
2

if not parcial1
print

5.0 and parcial2

if not parcial1
print

5.0 or not parcial2

5.0

Lee bien la condicin: si no es cierto que has sacado al menos un 5 en ambos (por eso el and)
parciales. . . . Ahora fjate en este otro fragmento:
1
2

5.0

Lemoslo: si no has sacado al menos un cinco en uno u otro (por eso el or) parcial. . . . O sea, los
dos fragmentos son equivalentes: uno usa un not que se aplica al resultado de una operacin and; el
otro usa dos operadores not cuyos resultados se combinan con un operador or. Y sin embargo, dicen
la misma cosa. Los lgicos utilizan una notacin especial para representar esta equivalencia:
(p q)

(p q)

p q,

p q.

(Los lgicos usan para not, para and y para or). Estas relaciones se deben al matemtico
De Morgan, y por su nombre se las conoce. Si es la primera vez que las ves, te resultarn chocantes,
pero si piensas un poco, vers que son de sentido comn.
Hemos observado que los estudiantes cometis errores cuando hay que expresar la condicin
contraria a una como a and b. Muchos escribs not a and not b y est mal. La negacin correcta
sera not a and b o, por De Morgan, not a or not b. Cul sera, por cierto, la negacin de
a or not b?

4.1.10.

Un ltimo problema: mens de usuario

Ya casi acabamos esta (largusima) seccin. Introduciremos una nueva estructura sintctica
planteando un nuevo problema. El problema es el siguiente: imagina que tenemos un programa
que a partir del radio de una circunferencia calcula su dimetro, permetro o rea. Solo queremos
mostrar al usuario una de las tres cosas, el dimetro, el permetro o el rea; la que l desee,
pero solo una.
Nuestro programa podra empezar pidiendo el radio del crculo. A continuacin, podra mostrar
un men con tres opciones: calcular el dimetro, calcular el permetro y calcular el rea.
Podramos etiquetar cada opcin con una letra y hacer que el usuario tecleara una de ellas. En
funcin de la letra tecleada, calcularamos una cosa u otra.
Analiza este programa:
1
2
3
4
5
6
7
8
9

from math import pi


radio

Men
print
print
print
print

float input

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

10
11
12
13
14
15
16
17
18
19
20
21
22

opcin

input

if opcin
dimetro
2
print
else
if opcin
permetro
print
else
if opcin
rea
print

Clculo del dimetro.


radio
format dimetro
2

pi

Clculo del permetro.


pi
radio
format permetro
Clculo del rea.
radio
2
format rea

Ejecutemos el programa y seleccionemos la segunda opcin:

Ejecutmoslo de nuevo, pero seleccionando esta vez la tercera opcin:

88
Nuestro aprendiz de programador ha tecleado en su ordenador el ltimo programa,
pero se ha despistado y ha escrito esto:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22

from math import pi


radio

float input

Men
print
print
print
print
opcin
input

if opcin
a
dimetro
2
print
else
if opcin
b
permetro
print
else
if opcin
rea
print

Clculo del dimetro.


radio
format dimetro
2

c
pi

Clculo del permetro.


pi
radio
format permetro
Clculo del rea.
radio
2
format rea

Las lneas sombreadas son diferentes de sus equivalentes del programa original. Funcionar
el programa del aprendiz? Si no es as, por qu motivo?
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Acabemos de pulir nuestro programa. Cuando el usuario no escribe ni la a, ni la b, ni la c al


tratar de seleccionar una de las opciones, deberamos decirle que se ha equivocado:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

from math import pi


radio

float input

Men
print
print
print
print
opcin
input

if opcin
dimetro
2
print
else
if opcin
permetro
print
else
if opcin
rea
print
else
print
print

Clculo del dimetro.


radio
format dimetro
2

pi

Clculo del permetro.


pi
radio
format permetro
Clculo del rea.
radio
2
format rea

format opcin

89
Haz una traza del programa suponiendo que el usuario teclea la letra
solicita una opcin. Qu lneas del programa se ejecutan?

cuando se le

90
El programa presenta un punto dbil: si el usuario escribe una letra mayscula en
lugar de minscula, no se selecciona ninguna opcin. Modifica el programa para que tambin
acepte letras maysculas.

4.1.11.

Una forma compacta para estructuras condicionales mltiples (elif)

El ltimo programa presenta un problema esttico: la serie de lneas que permiten seleccionar
el clculo que hay que efectuar segn la opcin de men seleccionada (lneas 1225) parece
ms complicada de lo que realmente es. Cada opcin aparece sangrada ms a la derecha que
la anterior, as que el clculo del rea acaba con tres niveles de sangrado. Imagina qu pasara
si el men tuviera 8 o 9 opciones: el programa acabara tan a la derecha que prcticamente se
saldra del papel! Python permite una forma compacta de expresar fragmentos de cdigo de la
siguiente forma:
1
2
3
4
5

if condicin

else
if otra condicin

Un else inmediatamente seguido por un if puede escribirse as:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4

if condicin

elif otra condicin

con lo que nos ahorramos un sangrado. El ltimo programa se convertira, pues, en este otro:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23

from math import pi


radio

float input

Men
print
print
print
print
opcin
input

if opcin
Clculo del dimetro.
dimetro
2
radio
print
format dimetro
elif opcin
Clculo del permetro.
permetro
2
pi
radio
print
format permetro
elif opcin
Clculo del rea.
rea
pi
radio
2
print
format rea
else
print
print
format opcin

El programa es absolutamente equivalente, ocupa menos lneas y gana mucho en legibilidad:


no solo evitamos mayores niveles de sangrado, tambin expresamos de forma clara que, en el
fondo, todas esas condiciones estn relacionadas.
Formas compactas: complicando las cosas?

Puede que comprender la estructura condicional if te haya supuesto un esfuerzo considerable.


A eso has tenido que aadir la forma if else. Y ahora el if elif! Parece que no hacemos ms que
complicar las cosas. Ms bien todo lo contrario: las formas if else e if elif (que tambin acepta
un if elif else) debes considerarlas una ayuda. En realidad, ninguna de estas formas permite hacer
cosas que no pudiramos hacer con solo el if, aunque, eso s, necesitando un esfuerzo mayor.
Mientras ests dando tus primeros pasos en la programacin, si dudas sobre qu forma utilizar,
trata de expresar tu idea con solo el if. Una vez tengas una solucin, plantate si tu programa se beneficiara del uso de una forma compacta. Si es as, sala. Ms adelante seleccionars instintivamente
la forma ms apropiada para cada caso. Bueno, eso cuando hayas adquirido bastante experiencia, y
solo la adquirirs practicando.

91
Modifica la solucin del ejercicio 85 usando ahora la estructura elif. No te parece
ms legible la nueva solucin?

4.2.

Sentencias iterativas

An vamos a presentar una ltima reflexin sobre el programa de los mens. Cuando el
usuario no escoge correctamente una opcin del men el programa le avisa, pero finaliza inmediatamente. Lo ideal sera que cuando el usuario se equivocara, el programa le pidiera de nuevo

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

una opcin. Para eso sera necesario repetir la ejecucin de las lneas 1023. Una aproximacin
naf consistira, bsicamente, en aadir al final una copia de esas lneas precedidas de un if que
comprobara que el usuario se equivoc. Pero esa aproximacin es muy mala: qu pasara si
el usuario se equivocara una segunda vez? Cuando decimos que queremos repetir un fragmento
del programa no nos referimos a copiarlo de nuevo, sino a ejecutarlo otra vez. Pero, es posible
expresar en este lenguaje que queremos que se repita la ejecucin de un trozo del programa?
Python permite indicar que deseamos que se repita un trozo de programa de dos formas
distintas: mediante la sentencia while y mediante la sentencia for. La primera de ellas es ms
general, por lo que la estudiaremos en primer lugar.

4.2.1.
1
2
3
4
5

La sentencia while

En ingls, while significa mientras. La sentencia while se usa as:

while condicin
accin
accin
accin

y permite expresar en Python acciones cuyo significado es:

Mientras se cumpla esta condicin, repite estas acciones.

Las sentencias que denotan repeticin se denominan bucles.


Vamos a empezar estudiando un ejemplo y viendo qu ocurre paso a paso. Estudia detenidamente este programa:
1
2
3
4
5

i
0
while i
3
print i
i
1
print

Observa que la lnea 2 finaliza con dos puntos ( ) y que el sangrado indica que las lneas
3 y 4 dependen de la lnea 2, pero no la lnea 5. Podemos leer el programa as: primero, asigna
a i el valor 0; a continuacin, mientras i sea menor que 3, repite estas acciones: muestra por
pantalla el valor de i e incrementa i en una unidad; finalmente, muestra por pantalla la palabra
Hecho.
Si ejecutamos el programa, por pantalla aparecer el siguiente texto:
Veamos qu ha ocurrido paso a paso con una traza.
Se ha ejecutado la lnea 1, con lo que i vale 0.

i=0
while i 3
print i
i
1
print

Despus, se ha ejecutado la lnea 2, que dice mientras i sea menor que 3, hacer. . . .
3, que ha resultado ser cierta. Como la condicin
Primero se ha evaluado la condicin i
se satisface, deben ejecutarse las acciones supeditadas a esta lnea (las dos siguientes,
que estn ms sangradas).
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

i=0
while i 3
print i
i
1
print

Se ejecuta en primer lugar la lnea 3, que muestra el valor de i por pantalla. Aparece,
pues, un cero.
i=0
while i 3
print i
i
1
print

Se ejecuta a continuacin la lnea 4, que incrementa el valor de i. Ahora i vale 1.


i=0
while i 3
print i
i
1
print

Ojo!, ahora no pasamos a la lnea 5, sino que volvemos a la lnea 2. Cada vez que
finalizamos la ejecucin de las acciones que dependen de un while, volvemos a la lnea
del while.
i=0
while i 3
print i
i
1
print

Estamos nuevamente en la lnea 2, as que comprobamos si i es menor que 3. Es as, por


lo que toca ejecutar de nuevo las lneas 3 y 4.
i=0
while i 3
print i
i
1
print

Volvemos a ejecutar la lnea 3, as que aparece un 1 por pantalla.


i=0
while i 3
print i
i
1
print

Volvemos a ejecutar la lnea 4, con lo que i vuelve a incrementarse y pasa de valer 1 a


valer 2.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

i=0
while i 3
print i
i
1
print

Nuevamente pasamos a la lnea 2. Siempre que acaba de ejecutarse la ltima accin de


un bucle while, volvemos a la lnea que contiene la palabra while. Como i sigue siendo
menor que 3, deberemos repetir las acciones expresadas en las lneas 3 y 4.
i=0
while i 3
print i
i
1
print

As que ejecutamos otra vez la lnea 3 y en pantalla aparece el nmero 2.


i=0
while i 3
print i
i
1
print

Incrementamos de nuevo el valor de i, como indica la lnea 4, as que i pasa de valer 2 a


valer 3.
i=0
while i 3
print i
i
1
print

Y de nuevo pasamos a la lnea 2. Pero ahora ocurre algo especial: la condicin no se


satisface, pues i ya no es menor que 3. Como la condicin ya no se satisface, no hay que
ejecutar otra vez las lneas 3 y 4. Ahora hemos de ir a la lnea 5, que es la primera lnea
que no est dentro del bucle.
i=0
while i 3
print i
i
1
print

Se ejecuta la lnea 5, que muestra por pantalla la palabra Hecho y finaliza el programa.
i=0
while i 3
print i
i
1
print

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Pero, por qu tanta complicacin? Este otro programa muestra por pantalla lo mismo, se entiende
ms fcilmente y es ms corto.
1
2
3
4

print 0
print 1
print 2
print

Bueno,
es un programa que solo pretende ilustrar el concepto de bucle, as
que ciertamente no hace nada demasiado til, pero aun as nos permite vislumbrar la potencia
del concepto de iteracin o repeticin. Piensa en qu ocurre si modificamos un solo nmero del
programa:
1
2
3
4
5

i
0
while i
1000
print i
i
1
print

Puedes escribir fcilmente un programa que haga lo mismo y que no utilice bucles?

1
2
3
4
5

1
2
3
4
5

1
2
3
4
5

1
2
3
4

92

Haz una traza de este programa:

93

Haz una traza de este programa:

94

Haz una traza de este programa:

95

Haz una traza de este programa:

i
0
while i
3
print i
i
1
print

i
0
while i
10
print i
i
2
print

i
3
while i
10
i
2
print i
print

i
1
while i
100
i
2
print i

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4

1
2
3
4

96

Haz una traza de este programa:

97

Haz unas cuantas trazas de este programa para diferentes valores de i.

i
10
while i
2
i
2
print i

i
int input
while i
10
print i
i
1

Qu ocurre si el valor de i es mayor o igual que 10? Y si es negativo?

1
2
3
4
5

98

Haz unas cuantas trazas de este programa para diferentes valores de i y de lmite.

i
int input
lmite
int input
while i
lmite
print i
i
1

99
Haz unas cuantas trazas de este programa para diferentes valores de i, de lmite y de
incremento.
1
2
3
4
5
6

i
int input
lmite
int input
incremento
int input
while i
lmite
print i
i
incremento

100
inclusive.

Implementa un programa que muestre todos los mltiplos de 6 entre 6 y 150, ambos

101
Implementa un programa que muestre todos los mltiplos de n entre n y m n, ambos
inclusive, donde n y m son nmeros introducidos por el usuario.

102
Implementa un programa que muestre todos los nmeros potencia de 2 entre 20 y
2 , ambos inclusive.
30

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Bucles sin fin

Los bucles son muy tiles a la hora de confeccionar programas, pero tambin son peligrosos si no
andas con cuidado: es posible que no finalicen nunca. Estudia este programa y vers qu queremos
decir:
E

1
2
3

i
0
while i
10
print i

La condicin del bucle siempre se satisface: dentro del bucle nunca se modifica el valor de i, y si
i no se modifica, jams llegar a valer 10 o ms. El ordenador empieza a mostrar el nmero 0 una y
otra vez, sin finalizar nunca. Es lo que denominamos un bucle sin fin o bucle infinito.
Cuando se ejecuta un bucle sin fin, el ordenador se queda como colgado y nunca nos devuelve el
control. Si ests ejecutando un programa desde la lnea de rdenes Unix o una consola de Windows,
puedes abortarlo pulsando
. Si la ejecucin tiene lugar en Eclipse/Pydev puedes abortar la
ejecucin del programa pulsando en el cuadrado rojo que aparece en la barra superior de la consola.

4.2.2.

Un problema de ejemplo: clculo de sumatorios

Ahora que ya hemos presentado lo fundamental de los bucles, vamos a resolver algunos
problemas concretos. Empezaremos por un programa que calcula la suma de los 1000 primeros
nmeros, es decir, un programa que calcula el sumatorio
1000

i=1

i,

o, lo que es lo mismo, el resultado de 1 + 2 + 3 + + 999 + 1000.


Vamos paso a paso. La primera idea que suele venir a quienes aprenden a programar es
reproducir la frmula con una sola expresin Python, es decir:
1
2

sumatorio
1
print sumatorio

999

1000

Pero, obviamente, no funciona: los puntos suspensivos no significan nada para Python. Aunque
una persona puede aplicar su intuicin para deducir qu significan los puntos suspensivos en
ese contexto, Python carece de intuicin alguna: exige que todo se describa de forma precisa y
rigurosa. Esa es la mayor dificultad de la programacin: el nivel de detalle y precisin con el
que hay que describir qu se quiere hacer.
Bien. Abordmoslo de otro modo. Vamos a intentar calcular el valor del sumatorio acumulando el valor de cada nmero en una variable. Analiza este otro programa (incompleto):
1
2
3
4
1000
1001
1002

sumatorio
sumatorio
sumatorio
sumatorio

1
2
3

sumatorio
999
sumatorio
1000
print sumatorio

Como programa no es el colmo de la elegancia. Fjate en que, adems, presenta una estructura
casi repetitiva: las lneas de la 2 a la 1001 son todas de la forma
sumatorio

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

nmero

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

donde nmero va tomando todos los valores entre 1 y 1000. Ya que esa sentencia, con ligeras
variaciones, se repite una y otra vez, vamos a tratar de utilizar un bucle. Empecemos construyendo
un borrador incompleto que iremos refinando progresivamente:
1
2
3
4

sumatorio
0
while condicin
sumatorio
print sumatorio

nmero

Hemos dicho que nmero ha de tomar todos los valores crecientes desde 1 hasta 1000.
Podemos usar una variable que, una vez inicializada, vaya tomando valores sucesivos con cada
iteracin del bucle:
1
2
3
4
5
6

sumatorio
0
i
1
while condicin
sumatorio
i
1
print sumatorio

Solo resta indicar la condicin con la que se decide si hemos de iterar de nuevo o, por el
contrario, hemos de finalizar el bucle:
1
2
3
4
5
6

sumatorio
0
i
1
while i
1000
sumatorio
i
i
1
print sumatorio

103
Estudia las diferencias entre el siguiente programa y el ltimo que hemos estudiado.
Producen ambos el mismo resultado?
1
2
3
4
5
6

sumatorio
0
i
0
while i
1000
i
1
sumatorio
print sumatorio

104

Disea un programa que calcule

m

i=n

i,

donde n y m son nmeros enteros que deber introducir el usuario por teclado.

105
Modifica el programa anterior para que si n > m, el programa no efecte ningn
clculo y muestre por pantalla un mensaje que diga que n debe ser menor o igual que m.

106
Queremos hacer un programa que calcule el factorial de un nmero entero positivo.
El factorial de n se denota con n!, pero no existe ningn operador Python que permita efectuar
este clculo directamente. Sabiendo que
n! = 1 2 3 . . . (n 1) n

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

y que 0! = 1, haz un programa que pida el valor de n y muestre por pantalla el resultado de
calcular n!.

107
El nmero de combinaciones que podemos formar tomando m elementos de un conjunto con n elementos es:
 
n!
n
.
Cmn =
=
(n m)! m!
m

Disea un programa que pida el valor de n y m y calcule Cmn . (Ten en cuenta que n ha de ser
mayor o igual que m).
(Puedes comprobar la validez de tu programa introduciendo los valores n = 15 y m = 10: el
resultado es 3003).

4.2.3.
1
2
3
4
5

Otro programa de ejemplo: requisitos en la entrada

Vamos con otro programa sencillo pero ilustrativo. Estudia este programa:

from math import sqrt


x

print

float input

format x

sqrt x

format x

sqrt x

format x

sqrt x

Como puedes ver, es muy sencillo: pide un nmero (flotante) y muestra por pantalla su raz
cuadrada. Como sqrt no puede trabajar con nmeros negativos, pedimos al usuario que introduzca
un nmero positivo. Pero nada obliga al usuario a introducir un nmero positivo.
En lugar de adoptar una solucin como las estudiadas anteriormente, esto es, evitando
ejecutar el clculo de la raz cuadrada cuando el nmero es negativo con la ayuda de una
sentencia condicional, vamos a obligar a que el usuario introduzca un nmero positivo repitiendo
la sentencia de la lnea 3 cuantas veces sea preciso. Dado que vamos a repetir un fragmento
de programa, utilizaremos una sentencia while. En principio, nuestro programa presentar este
aspecto:
1
2
3
4
5
6

from math import sqrt


while condicin
x
float input
print

Qu condicin poner? Est claro: el bucle debera leerse as mientras x sea un valor
invlido, hacer. . . , es decir, mientras x sea menor que cero, hacer. . . ; y esa ltima frase se
traduce a Python as:
1
2
3
4
5
6

from math import sqrt


while x
0
x
float input
print

Pero el programa no funciona correctamente. Mira qu obtenemos al ejecutarlo:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Python nos indica que la variable x no est definida (no existe) en la lnea 3. Qu ocurre?
Vayamos paso a paso: Python empieza ejecutando la lnea 1, con lo que importa la funcin sqrt
del mdulo math; la lnea 2 est en blanco, as que, a continuacin, Python ejecuta la lnea 3, lo
cual pasa por saber si la condicin del while es cierta o falsa. Y ah se produce el error, pues se
intenta conocer el valor de x cuando x no est inicializada. Es necesario, pues, inicializar antes
la variable; pero, con qu valor? Desde luego, no con un valor positivo. Si x empieza tomando
un valor positivo, la lnea 4 no se ejecutar. Probemos, por ejemplo, con el valor 1.
1
2
3
4
5
6
7

from math import sqrt


x
1
while x
0
x
float input
print

Ahora s. Hagamos una traza.

format x

sqrt x

1) Empezamos ejecutando la lnea 1, con lo que importa la funcin sqrt.


2) La lnea 2 se ignora.

3) Ahora ejecutamos la lnea 3, con lo que x vale 1.

4) En la lnea 4 nos preguntamos: es x menor que cero? La respuesta es s, de modo que


debemos ejecutar la lnea 5.
5) La lnea 5 hace que se solicite al usuario un valor para x. Supongamos que el usuario
introduce un nmero negativo, por ejemplo, 3.

6) Como hemos llegado al final de un bucle while, volvemos a la lnea 4 y nos volvemos a
preguntar es x menor que cero? De nuevo, la respuesta es s, as que pasamos a la lnea 5.
7) Supongamos que ahora el usuario introduce un nmero positivo, pongamos que el 16.

8) Por llegar al final de un bucle, toca volver a la lnea 4 y plantearse la condicin: es x menor
que cero? En este caso la respuesta es no, as que salimos del bucle y pasamos a ejecutar la
lnea 7, pues la lnea 6 est vaca.
9) La lnea 7 muestra por pantalla
hemos acabado.

. Y ya

Fjate en que las lneas 45 se pueden repetir cuantas veces haga falta: solo es posible salir
del bucle introduciendo un valor positivo en x. Ciertamente hemos conseguido obligar al usuario
a que los datos que introduce satisfagan una cierta restriccin.
1
2
3
4
5
6
7

108

Qu te parece esta otra versin del mismo programa?

from math import sqrt


x
float input
while x
0
x
float input
print

format x

sqrt x

109
Disea un programa que solicite la lectura de un nmero entre 0 y 10 (ambos inclusive). Si el usuario teclea un nmero fuera del rango vlido, el programa solicitar nuevamente
la introduccin del valor cuantas veces sea menester.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

110
Disea un programa que solicite la lectura de un texto que no contenga letras
maysculas. Si el usuario teclea una letra mayscula, el programa solicitar nuevamente la
introduccin del texto cuantas veces sea preciso.

111
Haz un programa que vaya leyendo nmeros y mostrndolos por pantalla hasta que
el usuario introduzca un nmero negativo. En ese momento, el programa mostrar un mensaje de
despedida y finalizar su ejecucin.

112
Haz un programa que vaya leyendo nmeros hasta que el usuario introduzca un
nmero negativo. En ese momento, el programa mostrar por pantalla el nmero mayor de
cuantos ha visto.

4.2.4.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21

Mejorando el programa de los mens

Al acabar la seccin dedicada a sentencias condicionales presentamos este programa:

from math import pi


radio

print
print
print
print
opcin

float input

input

if opcin
dimetro
2
radio
print
dimetro
elif opcin
permetro
2
pi
radio
print
permetro
elif opcin
rea
pi
radio
2
print
rea
else
print

opcin

Y al empezar esta seccin, dijimos que cuando el usuario no introduce correctamente una de
las tres opciones del men nos gustara volver a mostrar el men hasta que escoja una opcin
vlida.
En principio, si queremos que el men vuelva a aparecer por pantalla cuando el usuario se
equivoca, deberemos repetir desde la lnea 5 hasta la ltima, as que la sentencia while deber
aparecer inmediatamente antes de la quinta lnea. El borrador del programa puede quedar as:
E
1
2
3
4
5
6
7
8
9

10
11
12

from math import pi


radio

float input

while opcin
or opcin
print
print
print
print
opcin
input
if opcin
dimetro
2
radio

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

13
14
15
16
17
18
19
20
21

print
elif opcin
permetro
print
elif opcin
rea
pi
print
else
print

pi

radio

radio
2
rea

dimetro

permetro
opcin

Parece correcto, pero no lo es. Por qu? El error estriba en que opcin no existe la primera
vez que ejecutamos la lnea 5. Nos hemos olvidado de inicializar la variable opcin! Desde luego,
,
o
, pues entonces el bucle no se ejecutara
el valor inicial de opcin no debera ser
(piensa por qu). Cualquier otro valor har que el programa funcione. Nosotros utilizaremos la
cadena vaca para inicializar opcin:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22

from math import pi


radio

float input

opcin
while opcin
or opcin
print
print
print
print
opcin
input
if opcin
dimetro
2
radio
print
dimetro
elif opcin
permetro
2
pi
radio
print
permetro
elif opcin
rea
pi
radio
2
print
rea
else
print

opcin

113
Es correcto este otro programa? En qu se diferencia del anterior? Cul te parece
mejor (si es que alguno de ellos te parece mejor)?
1
2
3
4

from math import pi


radio

float input

opcin
while opcin
or opcin
print
print
print
print
opcin
input
if opcin
or opcin
print

opcin

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

5
6
7
8
9

10
11
12
13
14
15
16

if opcin
dimetro

radio

ndice

17
18
19
20
21
22
23

print
elif opcin
permetro
print
elif opcin
rea
pi
print

pi

radio

radio
2
rea

dimetro

permetro

Es habitual que los programas con men repitan una y otra vez las acciones de presentacin
del listado de opciones, lectura de seleccin y ejecucin del clculo. Una opcin del men permite
que finaliza cuando el
finalizar el programa. Aqu tienes una nueva versin de
usuario desea:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

from math import pi


radio

float input

opcin
while opcin
print
print
print
print
print
opcin
input
if opcin
dimetro
2
radio
print
dimetro
elif opcin
permetro
2
pi
radio
print
permetro
elif opcin
rea
pi
radio
2
print
rea
elif opcin
print
print

opcin

114
El programa anterior pide el valor del radio al principio y, despus, permite seleccionar uno o ms clculos con ese valor del radio. Modifica el programa para que pida el valor
del radio cada vez que se solicita efectuar un nuevo clculo.

115
Un vector en un espacio tridimensional es una tripleta de valores reales (x, y, z).
Deseamos confeccionar un programa que permita operar con dos vectores. El usuario ver en
pantalla un men con las siguientes opciones:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Puede que necesites que te refresquemos la memoria sobre los clculos a realizar. Si es as,
la tabla 4.1 te ser de ayuda:
Operacin

Clculo

Suma: (x1 , y1 , z1 ) + (x2 , y2 , z2 )

(x1 + x2 , y1 + y2 , z1 + z2 )

Producto vectorial: (x1 , y1 , z1 ) (x2 , y2 , z2 )

(y1 z2 z1 y2 , z1 x2 x1 z2 , x1 y2 y1 x2 )


180
x1 x2 + y1 y2 + z1 z2

arc cos  2

x1 + y21 + z12 x22 + y22 + z22



x 2 + y2 + z 2

Diferencia: (x1 , y1 , z1 ) (x2 , y2 , z2 )

Producto escalar: (x1 , y1 , z1 ) (x2 , y2 , z2 )


ngulo entre (x1 , y1 , z1 ) y (x2 , y2 , z2 )
Longitud de (x, y, z)

(x1 x2 , y1 y2 , z1 z2 )

x1 x2 + y1 y2 + z1 z2

Tabla 4.1: Recordatorio de operaciones bsicas sobre vectores.

Tras la ejecucin de cada una de las acciones del men este reaparecer en pantalla, a
menos que la opcin escogida sea la nmero 9. Si el usuario escoge una opcin diferente, el
programa advertir al usuario de su error y el men reaparecer.
Las opciones 4 y 6 del men pueden proporcionar resultados distintos en funcin del orden
de los operandos, as que, si se escoge cualquiera de ellas, deber mostrarse un nuevo men que
permita seleccionar el orden de los operandos. Por ejemplo, la opcin 4 mostrar el siguiente
men:

Nuevamente, si el usuario se equivoca, se le advertir del error y se le permitir corregirlo.


La opcin 8 del men principal conducir tambin a un submen para que el usuario decida
sobre cul de los dos vectores se aplica el clculo de longitud.
Ten en cuenta que tu programa debe contemplar y controlar toda posible situacin excepcional: divisiones por cero, races con argumento negativo, etctera. (Nota: La funcin arcocoseno
se encuentra disponible en el mdulo math y su identificador es acos).

4.2.5.

El bucle for in

Hay otro tipo de bucle en Python: el bucle for in, que se puede leer como para todo
elemento de una serie, hacer. . . . Un bucle for in presenta el siguiente aspecto:
1
2
3
4
5

1
2

for variable in serie de valores


accin
accin
accin

Veamos cmo funciona con un sencillo ejemplo:

for nombre in
print

format nombre

Fjate en que la relacin de nombres va encerrada entre corchetes y que cada nombre se
separa del siguiente con una coma. Se trata de una lista de nombres. Ms adelante estudiaremos
con detalle las listas. Ejecutemos ahora el programa. Por pantalla aparecer el siguiente texto:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Se ha ejecutado la sentencia ms sangrada una vez por cada valor de la serie de nombres
y, con cada iteracin, la variable nombre ha tomado el valor de uno de ellos (ordenadamente, de
izquierda a derecha).
Estudia este programa:
1
2
3
4
5
6

1
2
3
4

nmero
print
print
print
print

int input

format
format
format
format

Podemos ofrecer una versin ms simple:

nmero

int input

for potencia in
print

nmero
nmero
nmero
nmero

2
3
4
5

format nmero

nmero
nmero
nmero
nmero

2
3
4
5

potencia

nmero

potencia

El bucle se lee de forma natural como para toda potencia en la serie de valores 2, 3, 4 y 5,
haz. . . .

116
Haz un programa que muestre la tabla de multiplicar de un nmero introducido por
teclado por el usuario. Aqu tienes un ejemplo de cmo se debe comportar el programa:

117
Realiza un programa que proporcione el desglose en billetes y monedas de una
cantidad entera de euros. Recuerda que hay billetes de 500, 200, 100, 50, 20, 10 y 5 y
monedas de 2 y 1 . Debes recorrer los valores de billete y moneda disponibles con uno o
ms bucles for in.

118
Haz un programa que muestre la raz n-sima de un nmero ledo por teclado, para
n tomando valores entre 2 y 100.

El ltimo ejercicio propuesto es todo un desafo a nuestra paciencia: teclear 99 nmeros


separados por comas supone un esfuerzo brbaro y conduce a un programa poco elegante.
Es hora de aprender una nueva funcin predefinida de Python que nos ayudar a evitar ese
tipo de problemas: la funcin range (que en ingls significa rango). En principio, range se usa
con dos argumentos: un valor inicial y un valor final (con matices). Si usamos range directamente
veremos que proporciona un resultado curioso:
La funcin range devuelve un objeto de tipo range, lo que resulta un tanto redundante. Un
objeto de este tipo es un enumerador o generador y su sentido es muy dinmico: solo lo
tiene cuando se usa para generar una secuencia de valores. Estudia este ejemplo:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2

for i in range 1
print i

Al ejecutar el programa, veremos lo siguiente por pantalla:

La secuencia de nmeros que genera range es usada por el bucle for in como serie de
valores a recorrer. Observa que la serie de valores generados comprende todos los enteros entre
los argumentos de la funcin, incluyendo al primero pero no al ltimo.
Hay una funcin especial que toma como argumento una secuencia cualquiera de valores
(y lo que devuelve range lo es) y construye con ella una lista: list. Viene bien para comprobar
rpidamente lo que devuelve range si en algn momento tienes dudas:

El ltimo ejercicio propuesto era pesadsimo: nos obligaba a escribir una serie de 99 nmeros! Con range resulta muchsimo ms sencillo. He aqu la solucin:
1
2
3
4

nmero

float input

for n in range 2
print

101

format n

nmero

nmero

1 n

Fjate en que range tiene por segundo argumento el valor 101 y no 100: recuerda que con range
el ltimo elemento de la lista no llega a ser el valor final.
Podemos utilizar la funcin range con uno, dos o tres argumentos. Si usamos range con un
argumento estaremos especificando nicamente el ltimo valor (ms uno) de la serie, pues el
primero vale 0 por defecto:
Si usamos tres argumentos, el tercero permite especificar un incremento para la serie de
valores. Observa en estos ejemplos qu listas de enteros devuelve range:
Fjate en que si pones un incremento negativo (un decremento), la lista va de los valores
altos a los bajos:

As pues, si el tercer argumento es negativo, la lista finaliza con un valor mayor que el
segundo argumento (y no menor).
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Finalmente, observa que es equivalente utilizar range con dos argumentos a utilizarla con
un valor del incremento igual a 1.

119
Haz un programa que muestre, en lneas independientes, todos los nmeros pares
comprendidos entre 0 y 200 (ambos inclusive).

120
Haz un programa que muestre, en lneas independientes y en orden inverso, todos
los nmeros pares comprendidos entre 0 y 200 (ambos inclusive).

121
Escribe un programa que muestre los nmeros pares positivos entre 2 y un nmero
cualquiera que introduzca el usuario por teclado.
Obi Wan

Puede resultar sorprendente que range a b incluya todos los nmeros enteros comprendidos
entre a y b, pero sin incluir b. En realidad la forma natural o ms frecuente de usar range es con
un solo parmetro, range n , que devuelve una lista con los n primeros nmeros enteros incluyendo
al cero (hay razones para que esto sea lo conveniente, ya llegaremos). Como incluye al cero y hay
n nmeros, no puede incluir al propio nmero n. Al extenderse el uso de range a dos argumentos, se
ha mantenido la compatibilidad eliminando el ltimo elemento. Una primera ventaja es que resulta
fcil calcular cuntas iteraciones realizar un bucle range a b : exactamente b
a. (Si el valor b
estuviera incluido, el nmero de elementos sera b
a
1).
Hay que ir con cuidado, pues es fcil equivocarse por uno. De hecho, equivocarse por uno es
tan frecuente al programar (y no solo con range) que hay una expresin para este tipo de error: un
error Obi Wan (Kenobi), que es ms o menos como suena en ingls off by one (pasarse o quedarse
corto por uno).

4.2.6.

for in como forma compacta de ciertos while

Ciertos bucles se ejecutan un nmero de veces fijo y conocido a priori. Por ejemplo, al
desarrollar el programa que calcula el sumatorio de los 1000 primeros nmeros utilizamos un
bucle que iteraba exactamente 1000 veces:
1
2
3
4
5
6

sumatorio
0
i
1
while i
1000
sumatorio
i
i
1
print sumatorio

El bucle se ha construido de acuerdo con un patrn, una especie de frase hecha del lenguaje
de programacin:
1
2
3
4

i
valor inicial
while i
valor final
acciones
i
1

En este patrn la variable i suele denominarse ndice del bucle.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Podemos expresar de forma compacta este tipo de bucles con un for in siguiendo este otro
patrn:
1
2

for i in range valor inicial


acciones

valor final

Fjate en que las cuatro lneas del fragmento con while pasan a expresarse con solo dos
gracias al for in con range.
El programa de clculo del sumatorio de los 1000 primeros nmeros se puede expresar ahora
de este modo:
1
2
3
4
5

sumatorio
0
for i in range 1 1001
sumatorio
i
print sumatorio

Bastante ms fcil de leer que usando un while!

122
Haz un programa que pida el valor de dos enteros n y m y que muestre por pantalla
el valor de
m

i.
i=n

Debes usar un bucle for in para el clculo del sumatorio.

123
Haz un programa que pida el valor de dos enteros n y m y que muestre por pantalla
el valor de
m

i2 .
i=n

124
Haz un programa que pida el valor de dos enteros n y m y calcule el sumatorio de
todos los nmeros pares comprendidos entre ellos (incluyndolos en el caso de que sean pares).

4.2.7.

Nmeros primos

Vamos ahora con un ejemplo ms. Nos proponemos construir un programa que nos diga si
un nmero (entero) es o no es primo. Recuerda: un nmero primo es aquel nmero mayor que 1
que solo es divisible por 1 y por s mismo.
Cmo empezar? Resolvamos un problema concreto, a ver qu estrategia seguiramos normalmente. Supongamos que deseamos saber si 7 es primo. Podemos intentar dividirlo por cada
uno de los nmeros entre 2 y 6. Si alguna de las divisiones es exacta, entonces el nmero no es
primo:
Dividendo Divisor Cociente Resto
7
2
3
1
7
3
2
1
7
4
1
3
7
5
1
2
7
6
1
1
Ahora estamos seguros: ninguno de los restos dio 0, as que 7 es primo. Hagamos que el
ordenador nos muestre esa misma tabla:
1
2
3

nmero

for divisor in range 2

nmero

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4
5

print
print

format nmero divisor


format nmero

end
divisor

nmero

divisor

(Recuerda que range 2 nmero genera todos los nmeros enteros comprendidos entre 2
y nmero 1). Aqu tienes el resultado de ejecutar el programa:

Est claro que probar todas las divisiones es fcil, pero, cmo nos aseguramos de que todos
los restos son distintos de cero? Una posibilidad es contarlos y comprobar que hay exactamente
2 restos no nulos:
nmero
1
2
3
4
5
6
7
8
9

10
11

nmero

restos_no_nulos
0
for divisor in range 2 nmero
if nmero
divisor
0
restos_no_nulos
1
if restos_no_nulos
print
else
print

nmero

format nmero

format nmero

Pero vamos a proponer un mtodo distinto basado en una idea feliz y que, ms adelante, nos
permitir acelerar notabilsimamente el clculo. Vale la pena que la estudies bien: la utilizars
siempre que quieras probar que toda una serie de valores cumple una propiedad. En nuestro
caso, la propiedad que queremos demostrar que cumplen todos los nmeros comprendidos entre
2 y nmero
1 es al dividir a nmero, da resto distinto de cero.
Empieza siendo optimista: supn que la propiedad es cierta y asigna a una variable el
valor cierto.
Recorre todos los nmeros y cuando alguno de los elementos de la secuencia no satisfaga
la propiedad, modifica la variable antes mencionada para que contenga el valor falso.

Al final de todo, mira qu vale la variable: si an vale cierto, es que nadie la puso a
falso, as que la propiedad se cumple para todos los elementos y el nmero es primo; y si
vale falso, entonces alguien la puso a falso y para eso es preciso que algn elemento
no cumpliera la propiedad en cuestin, por lo que el nmero no puede ser primo.

Mira cmo plasmamos esa idea en un programa:


1
2
3
4
5
6
7
8
9

10
11

nmero

creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
if creo_que_es_primo
print
else
print

125

format nmero

format nmero

Haz un traza del programa para los siguientes valores de la variable nmero:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

a) 4

b) 13
c) 25

d) 2

1
2
3
4
5
6
7
8
9

10
11

Fjate en la lnea 8 de este programa:

nmero

True

True

creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
if creo_que_es_primo
print
else
print

format nmero

format nmero

La condicin del if es muy extraa, no? No hay comparacin alguna. Qu condicin es esa?
Muchos estudiantes optan por esta frmula alternativa para las lneas 8 y similares:
1
2
3
4
5
6
7
8
9

10
11

nmero

creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
if creo_que_es_primo
print
else
print

True

format nmero

format nmero

Les parece ms natural porque de ese modo se compara el valor de creo_que_es_primo con algo.
Pero, si lo piensas bien, esa comparacin es superflua: a fin de cuentas, el resultado de la comparacin
creo_que_es_primo
True es True, precisamente lo que ya vale creo_que_es_primo.
No es que est mal efectuar esa comparacin extra, sino que no aporta nada y resta legibilidad.
Evtala si puedes.

Despus de todo, no es tan difcil. Aunque esta idea feliz la utilizars muchas veces, es
probable que cometas un error (al menos, muchos compaeros tuyos caen en l una y otra vez).
Fjate en este programa, que est mal:
E
1
2
3
4
5
6
7
8
9

10

nmero

creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
else
creo_que_es_primo
True
if creo_que_es_primo

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

11
12
13

else

print

format nmero

print

format nmero

El programa solo se acuerda de lo que pas con el ltimo valor del bucle! Haz la prueba:
haz una traza sustituyendo la asignacin de la lnea 1 por la sentencia nmero 4. El nmero
no es primo, pero al no ser exacta la divisin entre 4 y 3 (el ltimo valor de divisor en el bucle),
el valor de creo_que_es_primo es True. El programa concluye, pues, que 4 es primo.
Se cumple para todos / se cumple para alguno

Muchos de los programas que disearemos necesitan verificar que cierta condicin se cumple para
algn elemento de un conjunto o para todos los elementos del conjunto. En ambos casos tendremos
que recorrer todos los elementos, uno a uno, y comprobar si la condicin es cierta o falsa para cada
uno de ellos.
Cuando queramos comprobar que todos cumplen una condicin, haremos lo siguiente:
1) Seremos optimistas y empezaremos suponiendo que la condicin se cumple para todos.
2) Preguntaremos a cada uno de los elementos si cumple la condicin.

3) Solo cuando detectemos que uno de ellos no la cumple, cambiaremos de opinin y pasaremos a
saber que la condicin no se cumple para todos. Nada nos podr hacer cambiar de opinin.

He aqu un esquema que usa la notacin de Python:


1
2
3
4
5
6

creo_que_se_cumple_para_todos
True
for elemento in conjunto
if not condicin
creo_que_se_cumple_para_todos
if creo_que_se_cumple_para_todos
print

False

Cuando queramos comprobar que alguno cumple una condicin, haremos lo siguiente:

1) Seremos pesimistas y empezaremos suponiendo que la condicin no se cumple para ninguno.


2) Preguntaremos a cada uno de los elementos si se cumple la condicin.

3) Solo cuando detectemos que uno de ellos s la cumple, cambiaremos de opinin y pasaremos a
saber que la condicin se cumple para alguno. Nada nos podr hacer cambiar de opinin.
He aqu un esquema que usa la notacin de Python:
1
2
3
4
5
6

creo_que_se_cumple_para_alguno
False
for elemento in conjunto
if condicin
creo_que_se_cumple_para_alguno
if creo_que_se_cumple_para_alguno
print

True

Vamos a refinar el programa. En primer lugar, haremos que trabaje con cualquier nmero
que el usuario introduzca:
1
2
3
4
5
6
7
8
9

10

nmero

int input

creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
if creo_que_es_primo
print
else

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

format nmero

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

print

11

format nmero

El programa presenta un punto dbil: cuando nmero toma el valor 1, el resultado proporcionado es incorrecto:
El nmero no es primo, pero al no ejecutarse ninguna vez el bucle for in, el valor de
creo_que_es_primo sigue siendo True. La solucin es fcil:
1
2
3

4
5
6
7
8
9

10
11
12
13
14

1
2
3
4
5
6
7
8
9

10
11
12
13
14

nmero

int input

if nmero
1
creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
else
creo_que_es_primo
False
if creo_que_es_primo
print
else
print

126

nmero

format nmero

format nmero

Sera correcta la siguiente versin del programa?


int input

if nmero
1
creo_que_es_primo
True
else
creo_que_es_primo
False
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
if creo_que_es_primo
print
else
print

format nmero

format nmero

Ahora vamos a hacer que el programa vaya ms rpido. Observa qu ocurre cuando tratamos
de ver si el nmero 1024 es primo o no. Empezamos dividindolo por 2 y vemos que el resto
de la divisin es cero. Pues ya est: estamos seguros de que 1024 no es primo. Sin embargo,
nuestro programa sigue haciendo clculos: pasa a probar con el 3, y luego con el 4, y con el 5,
y as hasta llegar al 1023. Para qu, si ya sabemos que no es primo? Nuestro objetivo es que
el bucle deje de ejecutarse tan pronto estemos seguros de que el nmero no es primo. Pero
resulta que no podemos hacerlo con un bucle for in, pues este tipo de bucles se basa en nuestro
conocimiento a priori de cuntas iteraciones vamos a hacer. Como en este caso no lo sabemos,
hemos de utilizar un bucle while. Escribamos primero un programa equivalente al anterior, pero
usando un while en lugar de un for in:
1
2

nmero

int input

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

3
4
5
6
7
8
9

10
11
12
13
14
15
16

if nmero
1
creo_que_es_primo
True
divisor
2
while divisor
nmero
if nmero
divisor
0
creo_que_es_primo
False
divisor
1
else
creo_que_es_primo
False
if creo_que_es_primo
print
else
print

127

format nmero

format nmero

Haz una traza del ltimo programa para el nmero 125.


Error para alguno / error para todos

Ya te hemos dicho que muchos de los programas que disearemos necesitan verificar que cierta
condicin se cumple para algn elemento de un conjunto o para todos los elementos del conjunto. Y
tambin te hemos dicho cmo abordar ambos problemas. Pero, aun as, es probable que cometas un
error (muchos, muchos estudiantes lo hacen). Aqu tienes un ejemplo de programa errneo al tratar de
comprobar que una condicin se cumple para todos los elementos de un conjunto:
1
2
3
4
5
6
7
8
9

creo_que_se_cumple_para_todos
True
for elemento in conjunto
if not condicin
creo_que_se_cumple_para_todos
False
else
Esta lnea y la siguiente sobran
creo_que_se_cumple_para_todos
True
if creo_que_se_cumple_para_todos
print

Y aqu tienes una versin errnea para el intento de comprobar que una condicin se cumple para
alguno:
1
2
3
4
5
6
7
8
9

creo_que_se_cumple_para_alguno
False
for elemento in conjunto
if condicin
creo_que_se_cumple_para_alguno
True
else
Esta lnea y la siguiente sobran
creo_que_se_cumple_para_alguno
False
if creo_que_se_cumple_para_alguno
print

En ambos casos, solo se est comprobando si el ltimo elemento del conjunto cumple o no la
condicin.

Hemos sustituido el for in por un while, pero no hemos resuelto el problema: con el 1024
seguimos haciendo todas las pruebas de divisibilidad. Cmo hacer que el bucle acabe tan pronto
se est seguro de que el nmero no es primo? Pues complicando un poco la condicin del while:
1
2
3
4

nmero

int input

if nmero
1
creo_que_es_primo

True

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5
6
7
8
9

10
11
12
13
14
15
16

else

divisor
2
while divisor
nmero and creo_que_es_primo
if nmero
divisor
0
creo_que_es_primo
False
divisor
1
creo_que_es_primo

if creo_que_es_primo
print
else
print

False

Ahora s.

128

format nmero

format nmero

Haz una traza del ltimo programa para el nmero 125.

129
Haz un programa que calcule el mximo comn divisor (mcd) de dos enteros positivos.
El mcd es el nmero ms grande que divide exactamente a ambos nmeros.

130
Haz un programa que calcule el mximo comn divisor (mcd) de tres enteros positivos.
El mcd de tres nmeros es el nmero ms grande que divide exactamente a los tres.

4.2.8.

Rotura de bucles: break

El ltimo programa diseado aborta su ejecucin tan pronto sabemos que el nmero estudiado
no es primo. La variable creo_que_es_primo juega un doble papel: recordar si el nmero es
primo o no al final del programa y abortar el bucle while tan pronto sabemos que el nmero
no es primo. La condicin del while se ha complicado un poco para tener en cuenta el valor de
creo_que_es_primo y abortar el bucle inmediatamente.
Hay una sentencia que permite abortar la ejecucin de un bucle desde cualquier punto del
mismo: break (en ingls significa romper). Observa esta nueva versin del mismo programa:)
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

nmero

int input

if nmero
1
creo_que_es_primo
True
divisor
2
while divisor
nmero
if nmero
divisor
0
creo_que_es_primo
False
break
divisor
1
else
creo_que_es_primo
False
if creo_que_es_primo
print
else
print

format nmero

format nmero

Cuando se ejecuta la lnea 9, el programa sale inmediatamente del bucle, es decir, pasa a la
lnea 13 sin pasar por la lnea 10.
Nuevamente estamos ante una comodidad ofrecida por el lenguaje: la sentencia break permite
expresar de otra forma una idea que ya poda expresarse sin ella. Solo debes considerar la
utilizacin de break cuando te resulte cmoda. No abuses del break: a veces, una condicin
bien expresada en la primera lnea del bucle while hace ms legible un programa.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

de
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15

La sentencia break tambin es utilizable con el bucle for in. Analicemos esta nueva versin
:

nmero

int input

if nmero
1
creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
break
else
creo_que_es_primo
False
if creo_que_es_primo
print
else
print

format nmero

format nmero

Esta versin es ms concisa que la anterior (ocupa menos lneas) y, en cierto sentido, ms
elegante: el bucle for in expresa mejor la idea de que divisor recorre ascendentemente un rango
de valores.
Versiones eficientes de se cumple para alguno / se cumple para todos

Volvemos a visitar los problemas de se cumple para alguno y se cumple para todos. Esta vez
vamos a hablar de cmo acelerar el clculo gracias a la sentencia break.
Si quieres comprobar si una condicin se cumple para todos los elementos de un conjunto y
encuentras que uno de ellos no la satisface, para qu seguir? Ya sabemos que no se cumple para
todos!
1
2
3
4
5
6
7
8

creo_que_se_cumple_para_todos
True
for elemento in conjunto
if not condicin
creo_que_se_cumple_para_todos
break
if creo_que_se_cumple_para_todos
print

False

Como ves, esta mejora puede suponer una notable aceleracin del clculo: cuando el primer
elemento del conjunto no cumple la condicin, acabamos inmediatamente. Ese es el mejor de los
casos. El peor de los casos es que todos cumplan la condicin, pues nos vemos obligados a recorrer
todos los elementos del conjunto. Y eso es lo que hacamos hasta el momento: recorrer todos los
elementos. O sea, en el peor de los casos, hacemos el mismo esfuerzo que venamos haciendo para
todos los casos. No est nada mal!
Si quieres comprobar si una condicin se cumple para alguno de los elementos de un conjunto y
encuentras que uno de ellos la satisface, para qu seguir? Ya sabemos que la cumple alguno!
1
2
3
4
5
6
7
8

creo_que_se_cumple_para_alguno
False
for elemento in conjunto
if condicin
creo_que_se_cumple_para_alguno
break
if creo_que_se_cumple_para_alguno
print

True

Podemos hacer la misma reflexin en torno a la eficiencia de esta nueva versin que en el caso
anterior.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

131

Haz una traza del programa para el valor 125.

132
En realidad no hace falta explorar todo el rango de nmeros entre 2 y n 1 para
saber si un nmero n es o no es primo. Basta con explorar el rango de nmeros entre 2 y la
parte entera de n/2. Piensa por qu. Modifica el programa para que solo exploremos ese rango.

133
Ni siquiera hace falta explorar todo el rango de nmeros entre 2 y n/2 para saber si
un nmero
n
es o no es primo. Basta con explorar el rango de nmeros entre 2 y la parte entera

de n. (Cretelo). Modifica el programa para que solo exploremos ese rango.

4.2.9.

Anidamiento de estructuras

Ahora vamos a resolver otro problema. Vamos a hacer que el programa pida un nmero y
nos muestre por pantalla los nmeros primos entre 1 y el que hemos introducido. Mira este
programa:
1
2
3
4
5
6
7
8
9

10
11

lmite

int input

for nmero in range 2 lmite 1


creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
break
if creo_que_es_primo
print nmero end
print

No debera resultarte difcil entender el programa. Tiene bucles anidados (un for in dentro
de un for in), pero est claro qu hace cada uno de ellos: el ms exterior recorre con nmero
todos los nmeros comprendidos entre 2 (pues ya sabemos que 1 no es primo) y lmite, ambos
inclusive; el ms interior forma parte del procedimiento que determina si el nmero que estamos
estudiando en cada instante es o no es primo.
Dicho de otro modo: nmero va tomando valores entre 2 y lmite y para cada valor de nmero
se ejecuta el bloque de las lneas 410, as que, para cada valor de nmero, se comprueba si
este es primo o no. Solo si el nmero resulta ser primo se muestra por pantalla.
Puede que te intrigue el break de la lnea 8. A qu bucle rompe? Solo al ms interior:
una sentencia break siempre aborta la ejecucin de un solo bucle y este es el que la contiene
directamente.
Probemos el programa
Antes de acabar: existen procedimientos ms eficientes para determinar si un nmero es
primo o no, as como para listar los nmeros primos en un intervalo. Hacer buenos programas no
solo pasa por conocer bien las reglas de escritura de programas en un lenguaje de programacin:
has de saber disear algoritmos y, muchas veces, buscar los mejores algoritmos conocidos en los
libros.
1)

134
1
2
3

Qu resultar de ejecutar estos programas?

for i in range 0 5
for j in range 0
print i j

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

ndice de bucle for in: prohibido asignar!

Hemos aprendido que el bucle for in utiliza una variable ndice a la que se van asignando los
diferentes valores del rango. En muchos ejemplos se utiliza la variable i, pero solo porque tambin
en matemticas los sumatorios y productorios suelen utilizar la letra i para indicar el nombre de su
variable ndice. Puedes usar cualquier nombre de variable vlido.
Pero que el ndice sea una variable cualquiera no te da libertad absoluta para hacer con ella lo
que quieras. En un bucle for in, las variables de ndice solo deben usarse para consultar su valor,
nunca para asignarles uno nuevo. Por ejemplo, este fragmento de programa es incorrecto:
1
2

for i in range 0
i
2

Y ahora que sabes que los bucles pueden anidarse, tambin has de tener mucho cuidado con sus
ndices. Un error frecuente entre primerizos de la programacin es utilizar el mismo ndice para dos
bucles anidados. Por ejemplo, estos bucles anidados estn mal:
1
2
3

for i in range 0 5
for i in range 0
print i

En el fondo, este problema es una variante del anterior, pues de algn modo se est asignando
nuevos valores a la variable i en el bucle interior, pero i es la variable del bucle exterior y asignarle
cualquier valor est prohibido.
Recuerda: nunca debes asignar un valor a un ndice de bucle for in ni usar la misma variable
ndice en bucles anidados.

2)

3)

4)

1
2
3

1
2
3

1
2
3
4

5)

1
2
3
4

6)

1
2
3

for i in range 0 5
for j in range i
print i j

for i in range 0 5
for j in range 0
print i j

for i in range 0 4
for j in range 0 4
for k in range 0 2
print i j k
for i in range 0 4
for j in range 0 4
for k in range i j
print i j k
for i in range 1 5
for j in range 0
print i j

10

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Una excepcin a la regla de sangrado

Cada vez que una sentencia acaba con dos puntos ( ), Python espera que la sentencia o sentencias
que le siguen aparezcan con un mayor sangrado. Es la forma de marcar el inicio y el fin de una serie
de sentencias que dependen de otra.
Hay una excepcin: si solo hay una sentencia que depende de otra, puedes escribir ambas en
la misma lnea. Este programa:
a
int input
while a
0
a
int input
if a
2
0
print
else
print

1
2
3
4
5
6
7

y este otro:

a
int input
while a
0 a
int input
if a
2
0 print
else print

1
2
3
4

son equivalentes, aunque el primero resulta ms legible.

4.3.

Captura y tratamiento de excepciones

Ya has visto que en nuestros programas pueden aparecer errores en tiempo de ejecucin,
es decir, pueden generar excepciones: divisiones por cero, intentos de calcular races de valores
negativos, problemas al operar con tipos incompatibles (como al sumar una cadena y un entero),
etc. Hemos presentado la estructura de control if como un medio para controlar estos problemas
y ofrecer un tratamiento especial cuando convenga (aunque luego hemos considerado muchas
otras aplicaciones de esta sentencia). En ocasiones, la deteccin de posibles errores con if
resulta un tanto pesada, pues modifica sensiblemente el aspecto del programa al llenarlo de
comprobaciones.
Hay una estructura de control especial para la deteccin y tratamiento de excepciones:
try except. Su forma bsica de uso es esta:
1
2
3
4
5
6
7
8
9

10

try

accin potencialmente errnea


accin potencialmente errnea

accin potencialmente errnea


except
accin para tratar el error
accin para tratar el error
accin para tratar el error

Podemos expresar la idea fundamental as:

Intenta ejecutar estas acciones y, si se comete un error, ejecuta inmediatamente estas otras.

Es fcil entender qu hace bsicamente si estudiamos un ejemplo sencillo. Volvamos a considerar


el problema de la resolucin de una ecuacin de primer grado:
1
2
3

a
b

float input
float input

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4
5
6
7
8
9

10
11

try

x
b a
print
except
if b
0
print
else
print

Las lneas 5 y 6 estn en un bloque que depende de la sentencia try. Es admisible que se
lancen excepciones desde ese bloque. Si se lanza una, la ejecucin pasar inmediatamente al
bloque que depende de la sentencia except. Hagamos dos trazas, una para una configuracin
de valores de a y b que provoque un error de divisin por cero y una para otra que no genere
excepcin alguna:
a=0yb=3
Las lneas 1 y 2 se ejecutan, con lo que se leen
los valores de a y b.
...........................................
La lnea 4 se ejecuta, pero no hay un efecto
asociado a su ejecucin.
...........................................
Al ejecutarse la lnea 5, se produce una excepcin (divisin por cero). Se salta inmediatamente a la lnea 8.
...........................................
Se ejecuta la lnea 8 y el resultado de la comparacin es cierto.
...........................................
La lnea 9 se ejecuta y se muestra por
pantalla el mensaje

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

a = 1 y b = 1
Las lneas 1 y 2 se ejecutan, con lo que se leen
los valores de a y b.
...........................................
La lnea 4 se ejecuta, pero no hay un efecto
asociado a su ejecucin.
...........................................
Se ejecutan las lneas 5 y 6, con lo que se
muestra por pantalla el valor de la solucin de
la ecuacin:
. La ejecucin finaliza.

Atrevmonos ahora con la resolucin de una ecuacin de segundo grado:

from math import sqrt


a
b
c

try

float input
float input
float input

x1
b
sqrt b 2
4 a c
2
a
x2
b
sqrt b 2
4 a c
2
a
if x1
x2
print
format x1
else
print
format x1 x2
except
No sabemos si llegamos aqu por una divisin por cero o si llegamos
por intentar calcular la raz cuadrada de un discriminante negativo.
print

Como es posible que se cometan dos tipos de error diferentes, al llegar al bloque dependiente del except no sabemos cul de los dos tuvo lugar. Evidentemente, podemos efectuar las
comprobaciones pertinentes sobre los valores de a, b y c para deducir el error concreto, pero
queremos contarte otra posibilidad de la sentencia try except. Las excepciones tienen un tipo
asociado y podemos distinguir el tipo de excepcin para actuar de diferente forma en funcin
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

del tipo de error detectado. Una divisin por cero es un error de tipo ZeroDivisionError y el
intento de calcular la raz cuadrada de un valor negativo es un error de tipo ValueError. Mmmm.
Resulta difcil recordar de qu tipo es cada error, pero el intrprete de Python resulta til para
recordar si provocamos deliberadamente un error del tipo que deseamos tratar:

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20

Es posible usar varias clusulas except, una por cada tipo de error a tratar:

from math import sqrt


a
b
c

try

float input
float input
float input

x1
b
sqrt b 2
x2
b
sqrt b 2
if x1
x2
print
else
print
except ZeroDivisionError
if b
0
print
else
print
except ValueError
print

4.4.

4.4.1.

4 a c
4 a c

2
2

a
a

format x1

format x1

x2

Algunos ejemplos grficos


Un graficador de funciones.

Vamos a usar el mdulo de la tortuga para representar grficamente funciones matemticas.


Utilizaremos la funcin seno, pero trataremos de que nuestro programa sea fcilmente modificable
para utilizar las que deseemos.
Como la funcin seno toma valores entre 1 y 1 y la vamos a representar en el intervalo
entre 2 y 2, vamos a empezar por definir la superficie de dibujo y el sistema de coordenadas
para la tortuga.
1
2
3
4
5
6
7

from turtle import Screen


from math import sin pi

Turtle

pantalla
Screen
pantalla setup 825 425
pantalla screensize 800 400
pantalla setworldcoordinates 2 pi

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

2 pi

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Dibujemos algunos puntos de la funcin. Usaremos el mtodo goto en lugar de giros con left
o right y desplazamientos con forward, pues queremos dibujar la funcin a partir de coordenadas
absolutas.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22

from turtle import Screen


from math import sin pi

Turtle

pantalla
Screen
pantalla setup 825 425
pantalla screensize 800 400
pantalla setworldcoordinates 2 pi
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga
tortuga

Turtle
penup
goto 2 pi sin 2 pi
pendown
goto 1.5 pi sin 1.5 pi
goto 1 pi sin 1 pi
goto 0.5 pi sin 0.5 pi
goto 0 sin 0
goto 0.5 pi sin 0.5 pi
goto 1 pi sin 1 pi
goto 1.5 pi sin 1.5 pi
goto 2 pi sin 2 pi

2 pi

pantalla exitonclick

El resultado no es muy suave:

Aparecen pocos puntos, pero podemos apreciar que estn dispuestos como corresponde a la
funcin seno. La cosa mejorara aadiendo ms puntos, pero desde luego que no lo haremos
repitiendo lneas en el programa como en el ejemplo: usaremos un bucle while.
La idea es hacer que una variable, digamos x, vaya recorriendo, paso a paso, el intervalo
[2, 2], y para cada valor, llamar a tortuga goto x sin x . Qu queremos decir con paso a
paso? Pues que de una iteracin a la siguiente, aumentaremos x en una cantidad fija. Pongamos,
inicialmente, que esta cantidad es 0.5. Nuestro programa presentar este aspecto:
1
2
3
4
5

from turtle import Screen


from math import sin pi
pantalla
Screen
pantalla setup 825

Turtle

425

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6
7
8
9

10
11
12
13
14
15
16
17
18
19

pantalla screensize 800 400


pantalla setworldcoordinates 2 pi
tortuga

Turtle

2 pi

x
valor inicial
tortuga penup
tortuga goto x sin x
tortuga pendown
while condicin
tortuga goto x sin x
x
0.5
pantalla exitonclick

Qu valor inicial asignamos a x? Podemos probar con 2, que es la coordenada X del


primer punto que nos interesa mostrar. Y qu condicin ponemos en el while? A ver, nos interesa
repetir mientras x sea menor o igual que 2. Pues ya est:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19

from turtle import Screen


from math import sin pi

Turtle

pantalla
Screen
pantalla setup 825 425
pantalla screensize 800 400
pantalla setworldcoordinates 2 pi
tortuga

Turtle

2 pi

x
2 pi
tortuga penup
tortuga goto x sin x
tortuga pendown
while x
2 pi
tortuga goto x sin x
x
0.5
pantalla exitonclick

El resultado es ahora mucho ms suave:

Aun as, nos gustara mostrar ms puntos. Ahora el cambio que debemos efectuar es muy sencillo:
en lugar de poner un incremento de 0.5, podemos poner un incremento ms pequeo. Cuanto
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

menor sea el incremento, ms puntos dibujaremos. Y si deseamos que aparezcan exactamente


800 puntos, que es la anchura de la superficie de dibujo? Muy sencillo: podemos calcular el
incremento dividiendo entre 800 el dominio de la funcin:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20

from turtle import Screen


from math import sin pi

Turtle

pantalla
Screen
pantalla setup 825 425
pantalla screensize 800 400
pantalla setworldcoordinates 2 pi
tortuga

Turtle

2 pi

x
2 pi
dx
4 pi
800
tortuga penup
tortuga goto x sin x
tortuga pendown
while x
2 pi
tortuga goto x sin x
x
dx
pantalla exitonclick

Este es el resultado:

Hagamos que el usuario pueda introducir el intervalo de valores de x que desea examinar, as
como el nmero de puntos que desee representar:
1
2
3
4
5
6
7
8
9

10
11
12
13

from turtle import Screen


from math import sin pi
x1
float input
x2
float input
puntos
int input

Turtle

pantalla
Screen
pantalla setup 825 425
pantalla screensize 800 400
pantalla setworldcoordinates x1
tortuga

Turtle

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

x2

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

14
15
16
17
18
19
20
21
22
23
24

x
x1
dx
x2
x1
puntos
tortuga penup
tortuga goto x sin x
tortuga pendown
while x
x2
tortuga goto x sin x
x
dx
pantalla exitonclick

Prueba el programa con diferentes valores de las variables. Fjate en qu programa tan til
hemos construido con muy pocos elementos: variables, bucles, el mdulo math y unas pocas
funciones predefinidas para trabajar con grficos.

135
usuario.

Haz un programa que muestre la funcin coseno en el intervalo que te indique el

136
Modifica el programa anterior para que se muestren dos funciones a la vez: la funcin
seno y la funcin coseno, pero cada una en un color distinto.

137
Haz un programa que muestre la funcin 1/(x + 1) en el intervalo [2, 2] con 100
puntos azules. Ten en cuenta que la funcin es problemtica en x = 1, por lo que dibujaremos
un punto rojo en las coordenadas (1, 0).
138
Haz un programa que, dados tres valores a, b y c, muestre la funcin f (x) = ax 2 +
bx +c en el intervalo [z1 , z2 ], donde z1 y z2 son valores proporcionados por el usuario. El programa
de dibujo debe calcular el valor mximo y mnimo de f (x) en el intervalo indicado para ajustar
el valor de pantalla setworldcoordinates de modo que la funcin se muestre sin recorte alguno.

139
Aade a la grfica del ejercicio anterior una representacin de los ejes coordenados
en color azul. Dibuja con crculos rojos los puntos en los que la parbola f (x) corta el eje
horizontal. Recuerda que la parbola corta al eje horizontal en los puntos x1 y x2 que son
solucin de la ecuacin de segundo grado ax 2 + bx + c = 0.

4.4.2.

Una animacin: simulacin gravitacional

Vamos a construir ahora un pequeo programa de simulacin gravitacional. Representaremos


en pantalla dos cuerpos y veremos qu movimiento presentan bajo la influencia mutua de la
gravedad en un universo bidimensional. Nos har falta repasar algunas nociones bsicas de
fsica.
La ley de gravitacin general de Newton nos dice que dos cuerpos de masas m1 y m2 se
atraen con una fuerza

m1 m2
,
r2
donde G es la constante de gravitacin universal y r es la distancia que separa a los cuerpos.
Sometido a esa fuerza, cada cuerpo experimenta una aceleracin. Recuerda que la aceleracin
a experimentada por un cuerpo de masa m sometido a una fuerza F es a = F /m. Cada cuerpo
experimentar una aceleracin distinta:
F =G

a1

a2

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

=
=

m2
,
r2
m1
G 2.
r
G

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Como los cuerpos ocupan las posiciones (x1 , y1 ) y (x2 , y2 ) en el plano, podemos dar una
formulacin vectorial de las frmulas anteriores:
a1

a2

=
=

donde los smbolos en negrita son vectores.


y2

y1

m1

r12
x1

m2 r12
,
r3
m1 r21
G 3 ,
r
G

m2

r21

x2

En particular, r12 es el vector (x2 x1 , y2 y1 ) y r21 es el vector (x1 x2 , y1 y2 ). El valor


de r, su mdulo, es

(x2 x1 )2 + (y2 y1 )2 .

La aceleracin afecta en cada instante de tiempo a la velocidad de cada cuerpo. Si un cuerpo


se desplaza en un instante dado a una velocidad (vx , vy ), una unidad de tiempo ms tarde se
desplazar a velocidad (vx + ax , vy + ay ), siendo (ax , ay ) su vector de aceleracin. El vector de
aceleracin del primer cuerpo es proporcional a r12 , y el del segundo cuerpo es proporcional
a r21 .
Ya basta de fsica. Volvamos al mundo de las tortugas. Representaremos cada cuerpo con
una tortuga con la forma de un crculo. Al crear una tortuga con Turtle podemos proporcionar un
parmetro de tipo cadena que indica la forma de la tortuga. Las formas disponibles son: flecha
(
), nada (
), crculo (
), clsica (
), cuadrado (
),
) y tortuga (
). Por otra parte, podemos asignar un color a cada
tringulo (
tortuga de modo que tanto la tortuga como su trazo se muestren en ese color. El mtodo color
admite una cadena con el color en cuestin (en ingls).
Con qu datos modelamos cada cuerpo? Una variable almacenar la masa de cada cuerpo,
eso est claro. Llamemos a esas variables m1 y m2. En cada instante, cada cuerpo ocupa una
posicin en el plano. Cada posicin se representa con dos valores: la posicin en el eje X y
la posicin en el eje Y . Las variables x1 e y1 almacenarn la posicin del primer cuerpo y las
variables x2 e y2 las del segundo. Otro dato importante es la velocidad que cada cuerpo lleva en
un instante dado. La velocidad es un vector, as que necesitamos dos variables para representarla.
Las variables velocidad_x1 y velocidad_y1 almacenarn el vector de velocidad del primer cuerpo
y las variables velocidad_x2 y velocidad_y2 el del segundo. Tambin la aceleracin de cada
cuerpo requiere dos variables y para representarla seguiremos el mismo patrn, solo que las
variables empezarn con el prefijo aceleracin.
Inicialmente cada cuerpo ocupa una posicin y lleva una velocidad determinada. Nuestro
programa puede empezar, de momento, as:
1
2
3

x1
200
y1
200
velocidad_x1

0.1

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4
5
6
7
8
9

10
11

velocidad_y1
m1
20
x2
200
y2
200
velocidad_x2
velocidad_y2
m2
20

0
0.1
0

Los clculos que nos permiten actualizar los valores de posicin y velocidad de cada cuerpo
son, de acuerdo con las nociones de fsica que hemos repasado, estos:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

from math import sqrt


x1
200
y1
200
velocidad_x1
velocidad_y1
m1
20
x2
200
y2
200
velocidad_x2
velocidad_y2
m2
20
r

sqrt

0.1
0

x2 x1

aceleracin_x1
aceleracin_y1
aceleracin_x2
aceleracin_y2
velocidad_x1
velocidad_y1
velocidad_x2
velocidad_y2
x1
y1
x2
y2

0.1
0

m2
m2
m1
m1

y2 y1

x2
y2
x1
y1

x1
y1
x2
y2

aceleracin_x1
aceleracin_y1
aceleracin_x2
aceleracin_y2

r 3
r 3
r 3
r 3

velocidad_x1
velocidad_y1
velocidad_x2
velocidad_y2

Advertirs que no hemos usado la constante de gravitacin G. Como afecta linealmente a la


frmula, su nico efecto prctico es acelerar la simulacin, as que hemos decidido prescindir
de ella.
Creemos la pantalla y hagamos que cada cuerpo se represente con una tortuga de un color
diferente:
1
2
3
4
5
6
7
8
9

10

from turtle import Screen


from math import sqrt

Turtle

pantalla
Screen
pantalla setup 1025 1025
pantalla screensize 1000 1000
pantalla setworldcoordinates 500
x1
y1

200
200

500

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

500

500

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

velocidad_x1
velocidad_y1
m1
20
x2
200
y2
200
velocidad_x2
velocidad_y2
m2
20
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo2
cuerpo2
cuerpo2
cuerpo2
cuerpo2
cuerpo2
r

sqrt

0.1
0

Turtle
color
speed 0
penup
goto x1 y1
pendown

Turtle
color
speed 0
penup
goto x2 y2
pendown
x2 x1

aceleracin_x1
aceleracin_y1
aceleracin_x2
aceleracin_y2
velocidad_x1
velocidad_y1
velocidad_x2
velocidad_y2
x1
y1
x2
y2

0.1
0

m2
m2
m1
m1

y2 y1

x2
y2
x1
y1

x1
y1
x2
y2

aceleracin_x1
aceleracin_y1
aceleracin_x2
aceleracin_y2

r 3
r 3
r 3
r 3

velocidad_x1
velocidad_y1
velocidad_x2
velocidad_y2

cuerpo1 goto x1 y1
cuerpo2 goto x2 y2
pantalla exitonclick

Hemos aprovechado para fijar la velocidad de las dos tortugas al mximo y para, tras ubicarlas
en sus respectivos puntos de partida, trasladarlas a la posicin que ocupan un instante de tiempo
despus.
Si queremos ver cmo evolucionan los cuerpos a lo largo del tiempo, deberemos repetir este
clculo numerosas veces, as que formar parte de un bucle. Para ver qu ocurre a lo largo de
10.000 unidades de tiempo, por ejemplo, insertaremos esa serie de acciones en un bucle al final
del cual se redibujan los dos cuerpos:
1
2
3
4
5
6

from turtle import Screen


from math import sqrt

Turtle

pantalla
Screen
pantalla setup 1025 1025
pantalla screensize 1000 1000

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

pantalla setworldcoordinates
x1
200
y1
200
velocidad_x1
velocidad_y1
m1
20
x2
200
y2
200
velocidad_x2
velocidad_y2
m2
20
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo2
cuerpo2
cuerpo2
cuerpo2
cuerpo2
cuerpo2

500

500

500

0.1
0
0.1
0

Turtle
color
speed 0
penup
goto x1 y1
pendown

Turtle
color
speed 0
penup
goto x2 y2
pendown

for t in range 10000


r
sqrt
x2 x1
aceleracin_x1
aceleracin_y1
aceleracin_x2
aceleracin_y2
velocidad_x1
velocidad_y1
velocidad_x2
velocidad_y2
x1
y1
x2
y2

500

m2
m2
m1
m1

y2 y1

x2
y2
x1
y1

x1
y1
x2
y2

aceleracin_x1
aceleracin_y1
aceleracin_x2
aceleracin_y2

r 3
r 3
r 3
r 3

velocidad_x1
velocidad_y1
velocidad_x2
velocidad_y2

cuerpo1 goto x1 y1
cuerpo2 goto x2 y2

pantalla exitonclick

Hay un escollo que salvar: la animacin es muy lenta. Es un efecto buscado por el diseador
del mdulo turtle, pues al ser un mdulo diseado con intencin pedaggica, las tortugas se
mueven lentamente y as resulta ms fcil percibir qu ocurre durante la ejecucin del programa
(especialmente si algo va mal). Pero el diseador dej una puerta abierta: con el mtodo delay
podemos fijar el tiempo que transcurre entre dos fotogramas de la animacin.
1
2
3

from turtle import Screen


from math import sqrt

Turtle

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

pantalla
pantalla
pantalla
pantalla
pantalla

Screen
setup 1025 1025
screensize 1000 1000
setworldcoordinates 500
delay 0

x1
200
y1
200
velocidad_x1
velocidad_y1
m1
20
x2
200
y2
200
velocidad_x2
velocidad_y2
m2
20
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo1
cuerpo2
cuerpo2
cuerpo2
cuerpo2
cuerpo2
cuerpo2

500

500

0.1
0
0.1
0

Turtle
color
speed 0
penup
goto x1 y1
pendown

Turtle
color
speed 0
penup
goto x2 y2
pendown

for t in range 10000


r
sqrt
x2 x1
aceleracin_x1
aceleracin_y1
aceleracin_x2
aceleracin_y2
velocidad_x1
velocidad_y1
velocidad_x2
velocidad_y2
x1
y1
x2
y2

500

m2
m2
m1
m1

y2 y1

x2
y2
x1
y1

x1
y1
x2
y2

aceleracin_x1
aceleracin_y1
aceleracin_x2
aceleracin_y2

r 3
r 3
r 3
r 3

velocidad_x1
velocidad_y1
velocidad_x2
velocidad_y2

cuerpo1 goto x1 y1
cuerpo2 goto x2 y2

pantalla exitonclick

Y ya est: ejecutemos el programa. He aqu el resultado final (en pantalla aparecer como
una animacin):
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Es momento de alguna optimizacin. Elevar un nmero al cubo es una operacin costosa. Nosotros
la efectuamos cuatro veces cuando una sola es suficiente. Deberamos calcular r 3 una sola vez,
almacenar el resultado en una variable y usar esa variable como divisor en las cuatro divisiones
que se efectan en cada bucle. Dejamos esta optimizacin como ejercicio para el lector.
Divirtete con el programa. He aqu algunas configuraciones iniciales interesantes:
1)

1
2
3
4
5
6
7
8
9

10
11

2)

1
2
3
4
5
6
7
8
9

10
11

x1
200
y1
200
velocidad_x1
velocidad_y1
m1
0.001
x2
200
y2
200
velocidad_x2
velocidad_y2
m2
20
x1
200
y1
200
velocidad_x1
velocidad_y1
m1
20
x2
200
y2
200
velocidad_x2
velocidad_y2
m2
20

0.1
0
0
0

0.1
0
0.1
0

140
Qu pasara si los dos cuerpos ocuparan exactamente la misma posicin en el
plano? Modifica el programa para que, si se da el caso, no se produzca error alguno y finalice
inmediatamente la ejecucin del bucle.
141
Modifica el programa para que la simulacin no finalice nunca (bueno, solo cuando
el usuario interrumpa la ejecucin del programa).

142
Seras capaz de extender el programa para que muestre la interaccin entre tres
cuerpos? Repasa la formulacin fsica del problema antes de empezar a programar.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4.5.

Una reflexin final

En este captulo te hemos presentado varias estructuras de control de flujo que, esencialmente, se reducen a dos conceptos: la seleccin condicional de sentencias y la repeticin condicional
de sentencias. En los primeros tiempos de la programacin no siempre se utilizaban estas estructuras: exista una sentencia comodn que permita saltar a cualquier punto de un programa:
(en ingls, ir-a).
la que se conoce como sentencia
Observa cmo se podra haber escrito el programa
(seccin 4.2.7) en el lenguaje
de programacin BASIC, que originariamente careca de estructuras como el bucle while:

Cada lnea del programa est numerada y la sentencia


indica en qu lnea debe
continuar la ejecucin del programa. Como es posible saltar a cualquier lnea en funcin de la
satisfaccin de una condicin, es posible montar a mano cualquier estructura de control. Ahora
bien, una cosa es que sea posible y otra que el resultado presente un mnimo de elegancia.
El programa BASIC del ejemplo es endiabladamente complejo: resulta difcil apreciar que las
lneas forman un bucle while. Los programas construidos abusando del
reciban el
nombre de cdigo spaghetti, pues al representar con flechas los posibles saltos del programa
se formaba una maraa que recuerda a un plato de spaghetti.
En los aos 70 hubo una corriente en el campo de la informtica que propugnaba la supresin
de la sentencia
. Edsger W. Dijkstra public un influyente artculo titulado Goto considered
considerada daina) en el que se haca una severa crtica al uso
harmful (La sentencia
de esta sentencia en los programas. Se demostr que era posible construir cualquier programa
con solo selecciones y repeticiones condicionales y que estos programas resultaban mucho ms
legibles. La denominada programacin estructurada es la corriente que propugna (entre otros
principios) la programacin usando nicamente estructuras de control (if, while, for in,. . . ) para
alterar el flujo del programa.
Al poco tiempo de su aparicin, la programacin estructurada se convirti en la metodologa
de programacin. (Los puristas de la programacin estructurada no solo censuran el uso de
sentencias
: tambin otras como break estn proscritas).
Hay que decir, no obstante, que programar es una forma de describir ideas algortmicas
siguiendo unas reglas sintcticas determinadas y que, en ocasiones, romper una regla permite
una mejor expresin. Pero, ojo!, solo estars capacitado para romper reglas cuando las conozcas
perfectamente. Por una cuestin de disciplina es preferible que, al principio, procures no utilizar
en absoluto alteraciones del flujo de control arbitrarias. . . aunque de todos modos no podrs
hacerlo de momento: Python no tiene sentencia
!

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Captulo 5

Tipos estructurados: secuencias

Primero llegaron diez soldados portando bastos: tenan la misma forma que los
tres jardineros, plana y rectangular, con las manos y los pies en las esquinas; luego
venan los diez cortesanos, todos adornados de diamantes, y caminaban de dos en
dos, como los soldados. Seguan los infantes: eran diez en total y era encantador
verlos venir cogidos de la mano, en parejas, dando alegres saltos: estaban adornados
con corazones.
Alicia en el pas de las maravillas, Lewis Carroll

Hasta el momento hemos tratado con datos de cuatro tipos distintos: enteros, flotantes, lgicos
y cadenas. Los tres primeros son tipos de datos escalares. Las cadenas, por contra, son tipos de
datos secuenciales. Un dato de tipo escalar es un elemento nico, atmico. Por contra, un dato
de tipo secuencial se compone de una sucesin de elementos y una cadena es una sucesin de
caracteres. Los datos de tipo secuencial son datos estructurados. En Python es posible manipular
los datos secuenciales de diferentes modos, facilitando as la escritura de programas que manejan
conjuntos o series de valores.
En algunos puntos de la exposicin nos desviaremos hacia cuestiones relativas al modelo de
memoria de Python. Aunque se trata de un material que debes comprender y dominar, no pierdas
de vista que lo realmente importante es que aprendas a disear e implementar algoritmos que
trabajan con secuencias.
En este captulo empezaremos aprendiendo ms de lo que ya sabemos sobre cadenas. Despus, te presentaremos las listas. Una lista es una sucesin de elementos de cualquier tipo.
Finalmente, aprenders a definir y manejar matrices: disposiciones bidimensionales de elementos. Python no incorpora un tipo de datos nativo para matrices, as que las construiremos como
listas de listas.

5.1.

5.1.1.

Cadenas

Lo que ya sabemos

Ya vimos en captulos anteriores que una cadena es una sucesin de caracteres. Python
ofrece una serie de operadores y funciones predefinidos que manipulan cadenas o devuelven
cadenas como resultado. Repasemos brevemente las que ya conocemos de captulos anteriores:

Operador (concatenacin de cadenas): acepta dos cadenas como operandos y devuelve


la cadena que resulta de unir la segunda a la primera.

Operador (repeticin de cadena): acepta una cadena y un entero y devuelve la concatenacin de la cadena consigo misma tantas veces como indica el entero.

int: recibe una cadena cuyo contenido es una secuencia de dgitos y devuelve el nmero
entero que describe.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

float: acepta una cadena cuyo contenido describe un flotante y devuelve el flotante en
cuestin.
str: se le pasa un entero o flotante y devuelve una cadena con una representacin del
valor como secuencia de caracteres.
ord: acepta una cadena compuesta por un nico carcter y devuelve su cdigo Unicode
(un entero).
chr: recibe un entero y devuelve una cadena con el carcter que tiene a dicho entero como
cdigo Unicode.

Podemos manipular cadenas, adems, mediante mtodos que les son propios:

a lower (paso a minsculas): devuelve una cadena con los caracteres de a convertidos
en minsculas.

a upper (paso a maysculas): devuelve una cadena con los caracteres de a convertidos
en maysculas.

a title (paso a palabras con inicial mayscula): devuelve una cadena en la que toda
palabra de a empieza por mayscula.

a format expr1 expr2 . . . ) (sustitucin de marcas de formato): devuelve una cadena en


la que las marcas de formato de a se sustituyen por el resultado de evaluar las expresiones
dadas.

Aprenderemos ahora a utilizar nuevas herramientas. Pero antes, estudiemos algunas peculiaridades de la codificacin de los caracteres en las cadenas.

5.1.2.

Escapes

Las cadenas que hemos estudiado hasta el momento consistan en sucesiones de caracteres
normales: letras, dgitos, signos de puntuacin, espacios en blanco. . . Es posible, no obstante,
incluir ciertos caracteres especiales que no tienen una representacin trivial.
Por ejemplo, los saltos de lnea se muestran en pantalla como eso, saltos de lnea, no como
un carcter convencional. Si intentamos incluir un salto de lnea en una cadena pulsando la
tecla de retorno de carro, Python se queja:

Ves? Al pulsar la tecla de retorno de carro, el intrprete de Python intenta ejecutar la


sentencia inmediatamente y considera que la cadena est inacabada, as que notifica que ha
detectado un error.
Observa esta otra asignacin de una cadena a la variable a y mira qu ocurre cuando
mostramos el contenido de a:
Al mostrar la cadena se ha producido un salto de lnea detrs de la palabra una. El salto de
lnea se ha codificado en la cadena con dos caracteres: la barra invertida y la letra n.
La barra invertida se denomina carcter de escape y es un carcter especial: indica que el
siguiente carcter tiene un significado diferente del usual. Si el carcter que le sigue es la letra
n, por ejemplo, se interpreta como un salto de lnea (la n viene del trmino new line, es decir,
nueva lnea). Ese par de caracteres forma una secuencia de escape y denota un nico carcter.
Y un salto de lnea es un nico carcter? S. Ocupa el mismo espacio en memoria que cualquier
otro carcter y se codifica internamente con un valor numrico (cdigo Unicode): el valor 10.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Cuando una impresora o un terminal de pantalla tratan de representar el carcter de cdigo 10, saltan de lnea. El carcter n es un carcter de control, pues su funcin es permitirnos
ejecutar una accin de control sobre ciertos dispositivos (como la impresora o el terminal).
Mostrar con y sin print

Es un buen momento para que veas la diferencia que supone usar o no usar la funcin print en
el intrprete interactivo a la hora de mostrar el valor de una variable:

Ves? Al mostrar directamente el valor de a, lo vemos como una cadena Python y, en consecuencia,
el salto de lnea aparece representado con . Por el contrario, si lo mostramos con print, se imprime
en pantalla cada elemento de la cadena, teniendo en cuenta que las comillas no son elementos de la
cadena (sino las marcas que usa Python para saber o sealar dnde empieza y acaba esta) y que el
carcter de salto de lnea provoca en pantalla un salto de lnea.

Hay muchos caracteres de control. Esta tabla muestra algunos:


Secuencia de escape
para carcter de control

ooo
hh

Resultado

Carcter de campana (
)
Espacio atrs ( )
Alimentacin de formulario ( )
Salto de lnea ( )
Retorno de carro ( )
Tabulador horizontal (
)
Tabulador vertical ( )
Carcter cuyo cdigo en octal es ooo
Carcter cuyo cdigo en hexadecimal es hh

Pero no te preocupes: nosotros utilizaremos fundamentalmente dos: n y t. Este ltimo representa el carcter de tabulacin horizontal o, simplemente, tabulador. El tabulador puede resultar til
para alinear en columnas datos mostrados por pantalla. Mira este ejemplo, en el que destacamos
los espacios en blanco de la salida por pantalla para que puedas contarlos:

Los elementos se alinean en la misma columna porque hay marcas de alineacin cada 8
columnas. El tabulador se interpreta como desplzate a la siguiente marca de alineacin.
Alternativamente, puedes usar el cdigo (en octal o hexadecimal) de un carcter de control
para codificarlo en una cadena, como se muestra en las dos ltimas filas de la tabla de secuencias
y en hexadecimal
de escape. El salto de lnea tiene cdigo 10, que en octal se codifica con
con
. Aqu te mostramos una cadena con tres saltos de lnea codificados de diferente forma:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ciertos caracteres no se pueden representar directamente en una cadena. La barra invertida


es uno de ellos. Para expresarla, debes usar dos barras invertidas seguidas:
En una cadena delimitada con comillas simples no puedes usar una comilla simple: si Python
, encuentra un error, pues cree que
trata de analizar una cadena mal formada, como
y no sabe cmo interpretar los caracteres
. Una comilla simple en
la cadena es
una cadena delimitada con comillas simples ha de ir precedida de la barra invertida. Lo mismo
ocurre con la comilla doble en una cadena delimitada con comillas dobles:
Estas secuencias de escape se pueden evitar la mayor parte de las veces escogiendo apropiadamente las comillas simples o dobles como delimitadores de la cadena:
Esta tabla complementa a la ltima:
Otras secuencias de escape

y salto de lnea

Resultado

Carcter barra invertida ( )


Comilla simple ( )
Comilla doble ( )
Se ignora (para expresar una cadena en varias lneas)

Fjate en el uso especial de la barra invertida al preceder a un carcter de salto de lnea:


Unix, Microsoft y Apple: condenados a no entenderse

Te hemos dicho que


codifica el carcter de control salto de lnea. Es cierto, pero no es toda
la verdad. En los antiqusimos sistemas de teletipo (bsicamente, mquinas de escribir controladas
por ordenador que se usaban antes de que existieran los monitores) se necesitaban dos caracteres
para empezar a escribir al principio de la siguiente lnea: un salto de lnea ( ) y un retorno de carro
( ). Si solo se enviaba el carcter
el carro saltaba a la siguiente lnea, s, pero se quedaba en
la misma columna. El carcter
haca que el carro retornase a la primera columna.
Con objeto de ahorrar memoria, los diseadores de Unix decidieron que el final de lnea en un
fichero debera marcarse nicamente con . Al disear MS-DOS, Microsoft opt por utilizar dos
caracteres:
. As pues, los ficheros de texto de Unix no son directamente compatibles con los de
Microsoft. Si llevas un fichero de texto de un sistema Microsoft a Unix vers que cada lnea acaba
con un smbolo extrao (el retorno de carro!), y si llevas el fichero de Unix a un sistema Microsoft,
parecer que las lneas estn mal alineadas.
Para poner peor las cosas, nos falta hablar de la decisin que adopt Apple en los ordenadores
Macintosh: usar solo el retorno de carro ( ). Tres sistemas operativos y tres formas distintas de decir
lo mismo!
De todos modos, no te preocupes en exceso, muchos editores de texto son suficientemente listos:
pueden detectar estas situaciones y las corrigen automticamente. En otros, el usuario puede ir a un
panel de preferencias y seleccionar el modo con el que se representan internamente los saltos de
lnea.

143

Qu se mostrar en pantalla al ejecutar estas sentencias?

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

(Te recomendamos que resuelvas este ejercicio a mano y compruebes la validez de tus respuestas con ayuda del ordenador).

144
dena?

Cmo crees que se pueden representar dos barras invertidas seguidas en una ca-

145
La secuencia de escape
emite un aviso sonoro (la campana). Qu hace exactamente cuando se imprime en pantalla? Ejecuta print
y lo averiguars.

146
Averigua el cdigo Unicode de los 10 primeros caracteres de la tabla en la que hemos
mostrado las secuencias de escape para caracteres de control.
Ms sobre la codificacin de las cadenas

Hemos visto que podemos codificar cadenas encerrando un texto entre comillas simples o entre
comillas dobles. En tal caso, necesitamos usar secuencias de escape para acceder a ciertos caracteres.
Python ofrece an ms posibilidades para codificar cadenas. Una de ellas hace que no se interpreten
las secuencias de escape, es decir, que todos sus caracteres se interpreten literalmente. Estas cadenas
directas (en ingls, raw strings) preceden con la letra r a las comillas (simples o dobles) que
la inician:

Cuando una cadena ocupa varias lneas, podemos usar la secuencia de escape
para marcar
cada salto de lnea. O podemos usar una cadena multilnea. Las cadenas multilnea empiezan con
tres comillas simples (o dobles) y finalizan con tres comillas simples (o dobles):

5.1.3.

Longitud de una cadena

La primera nueva funcin que estudiaremos es len (abreviatura del ingls length, en espaol,
longitud) que devuelve la longitud de una cadena, es decir, el nmero de caracteres que la
forman. Se trata de una funcin predefinida, as que podemos usarla directamente:

Hay una cadena que merece especial atencin, la cadena que denotamos abriendo y cerrando
inmediatamente las comillas simples, , o dobles, , sin ningn carcter entre ellas. Qu valor
?
devuelve len

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

La cadena
se denomina cadena vaca y tiene longitud cero. No confundas la cadena
, pues, aunque parecidas, no son
vaca, , con la cadena que contiene un espacio en blanco,
iguales. Fjate bien en que la segunda cadena contiene un carcter (el espacio en blanco) y, por
tanto, es de longitud 1. Podemos comprobarlo fcilmente:

5.1.4.

Indexacin

Podemos acceder a cada uno de los caracteres de una cadena utilizando un operador de
indexacin. El ndice del elemento al que queremos acceder debe encerrarse entre corchetes. Si
a es una cadena, a i es el carcter que ocupa la posicin i 1. Debes tener en cuenta que el
primer elemento tiene ndice cero. Los ndices de la cadena
se muestran en
esta figura:
0

10

11

Observa que el ltimo carcter de la cadena almacenada en la variable a no es a len a ,


sino a len a 1 . Por qu? Evidentemente, si el primer carcter tiene ndice 0 y hay len a
caracteres, el ltimo ha de tener ndice len a 1. Si intentamos acceder al elemento a len a ,
Python protesta:

El error cometido es del tipo IndexError (error de indexacin) y, en el texto explicativo que
lo detalla, Python nos informa de que el ndice de la cadena est fuera del rango de valores
vlidos.
Recuerda que las secuencias de escape codifican caracteres simples, aunque se expresen con
dos caracteres. La cadena
, por ejemplo, no ocupa 13 casillas, sino 12:
0

10

11

Tambin puedes utilizar ndices negativos con un significado especial: los valores negativos
acceden a los caracteres de derecha a izquierda. El ltimo carcter de una cadena tiene ndice
1, el penltimo, 2, y as sucesivamente. Analiza este ejemplo:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

De este modo se simplifica notablemente el acceso a los caracteres del final de la cadena.
Es como si dispusieras de un doble juego de ndices:

147
La ltima letra del DNI puede calcularse a partir de sus nmeros. Para ello solo
tienes que dividir el nmero por 23 y quedarte con el resto. El resto es un nmero entre 0 y 22.
La letra que corresponde a cada nmero la tienes en esta tabla:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

Disea un programa que lea de teclado un nmero de DNI y muestre en pantalla la letra que
le corresponde.
(Nota: una implementacin basada en tomar una decisin con if elif conduce a un programa
muy largo. Si usas el operador de indexacin de cadenas de forma inteligente, el programa
apenas ocupa tres lneas. Piensa cmo).

5.1.5.

Recorrido de cadenas

Una propiedad interesante de los datos secuenciales es que pueden recorrerse de izquierda
a derecha con un bucle for in. Por ejemplo, el siguiente bucle recorre los caracteres de una
cadena de uno en uno, de izquierda a derecha:

En cada paso, la variable del bucle (en el ejemplo, carcter) toma el valor de uno de los
caracteres de la cadena. Es lo que caba esperar: recuerda que el bucle for in recorre uno a
uno los elementos de una serie de valores, y una cadena es una secuencia de caracteres.
Tienes una forma alternativa de recorrer los elementos de una cadena: recorriendo el rango
de valores que toma su ndice e indexando cada uno de ellos. Estudia este ejemplo:

La variable i toma los valores de range len a , en este caso los valores comprendidos entre
0 y 8, ambos inclusive. Con a i hemos accedido, pues, a cada uno de ellos. Si mostramos tanto
i como a i , quizs entiendas mejor qu ocurre exactamente:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Tambin puedes mostrar los caracteres de la cadena en orden inverso, aunque en tal caso
has de hacerlo necesariamente con un bucle for in y un range:

148

Intentamos mostrar los caracteres de la cadena en orden inverso as:

Funciona?

149

Intentamos mostrar los caracteres de la cadena en orden inverso as:

Funciona?

150
Disea un programa que lea una cadena y muestre el nmero de espacios en blanco
que contiene.

151
Disea un programa que lea una cadena y muestre el nmero de letras maysculas
que contiene.
152

Disea un programa que lea una cadena y muestre en pantalla el mensaje


si contiene algn dgito y
en caso contrario.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5.1.6.

Un ejemplo: un contador de palabras

Ahora que tenemos nuevas herramientas para la manipulacin de cadenas, vamos a desarrollar un programa interesante: leer cadenas de teclado y mostrar en pantalla el nmero de
palabras que contienen.
Empecemos estudiando el problema con un ejemplo concreto. Cuntas palabras hay en la
cadena
? Tres palabras. Cmo lo sabemos? Muy fcil: contando los espacios
en blanco. Si hay dos espacios en blanco, entonces hay tres palabras, ya que cada espacio
separa dos palabras. Hagamos, pues, que el programa cuente el nmero de espacios en blanco
y muestre ese nmero ms uno:
1
2
3
4
5
6
7
8
9

10

cadena
input
while cadena
blancos
0
for carcter in cadena
if carcter
blancos
1
palabras
blancos
1 Hay una palabra ms que blancos
print
palabras
cadena

input

El programa finaliza la ejecucin cuando tecleamos una cadena vaca, es decir, si pulsamos
retorno de carro directamente. Ejecutemos el programa:

Eh! Qu ha pasado con el ltimo ejemplo? Hay dos palabras y el programa dice que hay
tres. Est claro: entre las palabras otro y ejemplo de la cadena
hay dos
espacios en blanco, y no uno solo. Corrijamos el programa para que trate correctamente casos
como este. Desde luego, contar espacios en blanco, sin ms, no es la clave para decidir cuntas
palabras hay. Se nos ocurre una idea mejor: mientras recorremos la cadena, veamos cuntas
veces pasamos de un carcter que no sea el espacio en blanco a un espacio en blanco. En la
pasamos dos veces de letra a espacio en blanco (una vez pasamos de
cadena
la al blanco y otra de la al blanco), y hay tres palabras; en la cadena problemtica
solo pasamos una vez (de la letra a un espacio en blanco) y, por tanto,
hay dos palabras. Si contamos el nmero de transiciones, el nmero de palabras ser ese mismo
nmero ms uno. Y cmo hacemos para comparar un carcter y su vecino? El truco est en
recordar siempre cul era el carcter anterior usando una variable auxiliar:
1
2
3
4
5
6
7
8
9

10
11
12

cadena
input
while cadena
cambios
0
anterior
for carcter in cadena
if carcter
and anterior
cambios
1
anterior
carcter
palabras
cambios
1 Hay una palabra ms que cambios de no blanco a blanco
print
palabras
cadena

input

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Por qu hemos dado un valor a anterior en la lnea 4? Para inicializar la variable. De no


hacerlo, tendramos problemas al ejecutar la lnea 6 por primera vez, ya que en ella se consulta
el valor de anterior.

153
Haz una traza del programa para la cadena
. Qu lneas se ejecutan y qu
valores toman las variables cambios, anterior y carcter tras la ejecucin de cada una de ellas?
154

dem para la cadena

Probemos nuestra nueva versin:

No! Otra vez mal! Qu ha ocurrido ahora? Si nos fijamos bien veremos que la cadena del
ltimo ejemplo acaba en un espacio en blanco, as que hay una transicin de no blanco a
espacio en blanco y eso, para nuestro programa, significa que hay una nueva palabra. Cmo
podemos corregir ese problema? Analicmoslo: parece que solo nos molestan los blancos al final
de la cadena. Y si descontamos una palabra cuando la cadena acaba en un espacio en blanco?
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16

cadena
input
while cadena
cambios
0
anterior
for carcter in cadena
if carcter
and anterior
cambios
1
anterior
carcter
if cadena 1
cambios
palabras
print
cadena

cambios

input

1
palabras

Probemos ahora esta nueva versin:

Perfecto! Ya est. Seguro? Mmmm. Los espacios en blanco dieron problemas al final de la
cadena. Sern problemticos tambin al principio de la cadena? Probemos:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

S, qu horror! Por qu falla ahora? El problema radica en la inicializacin de anterior


(lnea 4). Hemos dado una cadena vaca como valor inicial y eso hace que, si la cadena empieza
por un blanco, la condicin de la lnea 6 se evale a cierto para el primer carcter, incrementando as la variable cambios (lnea 7) la primera vez que iteramos el bucle. Podramos evitarlo
modificando la inicializacin de la lnea 4: un espacio en blanco nos vendra mejor como valor
inicial de anterior.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16

cadena
input
while cadena
cambios
0
anterior
for carcter in cadena
if carcter
and anterior
cambios
1
anterior
carcter
if cadena 1
cambios
palabras
print
cadena

Ahora s:

cambios

input

1
palabras

155
Funciona el programa cuando introducimos una cadena formada solo por espacios
en blanco? Por qu? Si su comportamiento no te parece normal, corrgelo.

El ejemplo que hemos desarrollado tiene un doble objetivo didctico. Por una parte, familiarizarte con las cadenas; por otra, que veas cmo se resuelve un problema poco a poco. Primero
hemos analizado el problema en busca de una solucin sencilla (contar espacios en blanco).
Despus hemos implementado nuestra primera solucin y la hemos probado con varios ejemplos.
Los ejemplos que nos hemos puesto no son solo los ms sencillos, sino aquellos que pueden
hacer cascar el programa (en nuestro caso, poner dos o ms espacios en blanco seguidos).
Detectar ese error nos ha conducido a una mejora del programa (en realidad, una correccin):
no debamos contar espacios en blanco, sino transiciones de no blanco a espacio en blanco.
Nuevamente hemos puesto a prueba el programa y hemos encontrado casos para los que falla (espacios al final de la cadena). Un nuevo refinamiento ha permitido tratar el fallo y, otra
vez, hemos encontrado un caso no contemplado (espacios al principio de la cadena) que nos ha
llevado a un ltimo cambio del programa. Fjate en que cada vez que hemos hecho un cambio
al programa hemos vuelto a introducir todos los casos que ya habamos probado (al modificar
un programa es posible que deje de funcionar para casos en los que ya iba bien) y hemos
aadido uno nuevo que hemos sospechado que poda ser problemtico. As es como se llega a la
solucin final: siguiendo un proceso reiterado de anlisis, prueba y error. Durante ese proceso
el programador debe jugar en dos equipos distintos:
a ratos juega en el equipo de los programadores y trata de encontrar la mejor solucin al
problema propuesto;

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

y a ratos juega en el equipo de los usuarios y pone todo su empeo en buscar configuraciones especiales de los datos de entrada que provoquen fallos en el programa.

156
Modifica el programa para que base el cmputo de palabras en el nmero de transiciones de blanco a no blanco en lugar de en el nmero de transiciones de no blanco a blanco.
Comprueba si tu programa funciona en toda circunstancia.

157
labras:
1
2
3
4
5
6
7
8
9

10
11
12
13
14

Nuestro aprendiz aventajado propone esta otra solucin al problema de contar pa-

cadena
input
while cadena
cambios
0
for i in range 1
if cadena i
cambios
if cadena 1
cambios
palabras
print
cadena

len cadena
and cadena i 1
cambios
1

cambios

input

1
palabras

Es correcta?

158
Disea un programa que lea una cadena y un nmero entero k y nos diga cuntas
palabras tienen una longitud de k caracteres.

159
Disea un programa que lea una cadena y un nmero entero k y nos diga si alguna
de sus palabras tiene una longitud de k caracteres.

160
Disea un programa que lea una cadena y un nmero entero k y nos diga si todas
sus palabras tienen una longitud de k caracteres.

161
Escribe un programa que lea una cadena y un nmero entero k y muestre el mensaje
si alguna de las palabras de la cadena es de longitud mayor o igual

en caso contrario.
que k, y

162
Escribe un programa que lea una cadena y un nmero entero k y muestre el mensaje
si todas las palabras de la cadena son de longitud estrictamente menor

en caso contrario.
que k, y

163
Escribe un programa que lea una cadena y un nmero entero k y muestre el mensaje
si todas las palabras de la cadena son de longitud mayor

en caso contrario.
o igual que k, y

164
Disea un programa que muestre la cantidad de dgitos que aparecen en una cadena
, por ejemplo, tiene 3 dgitos: un 1, un 2 y
introducida por teclado. La cadena
un 0.

165
Disea un programa que muestre la cantidad de nmeros que aparecen en una
cadena leda de teclado. Ojo! Con nmero no queremos decir dgito, sino nmero propiamente
, por ejemplo, tiene
dicho, es decir, secuencia de dgitos. La cadena
3 nmeros: el 1, el 201 y el 2.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

166
Disea un programa que indique si una cadena leda de teclado est bien formada
en caso afirmativo y

como nmero entero. El programa escribir


en caso contrario.
mostrar
, pero para
o
mostrar
Por ejemplo, para
.

167
Disea un programa que indique si una cadena introducida por el usuario est bien

formada como identificador de variable. Si lo est, mostrar el texto


y si no,
.

168
Disea un programa que indique si una cadena leda por teclado est bien formada
como nmero flotante.
,
,
,
,
,
,
Prueba el programa con estas cadenas:
. En todos los casos deber indicar que se trata de nmeros flotantes correctamente
formados.

169
Un texto est bien parentizado si por cada parntesis abierto hay otro ms adelante
que lo cierra. Por ejemplo, la cadena
est bien parentizada, pero no lo estn estas otras:
Disea un programa que lea una cadena y nos diga si la cadena est bien o mal parentizada.

170
Implementa un programa que lea de teclado una cadena que representa un nmero
binario. Si algn carcter de la cadena es distinto de
o
, el programa advertir al usuario
de que la cadena introducida no representa un nmero binario y pedir de nuevo la lectura de
la cadena.

5.1.7.

Otro ejemplo: un programa de conversin de binario a decimal

Nos proponemos disear un programa que reciba una cadena compuesta por ceros y unos
y muestre un nmero: el que corresponde al valor decimal de la cadena si interpretamos esta
como un nmero codificado en binario. Por ejemplo, nuestro programa mostrar el valor 13 para
la cadena
.
Empezaremos por plantearnos cmo haramos manualmente el clculo. Podemos recorrer la
cadena de izquierda a derecha e ir considerando el aporte de cada bit al nmero global. El
, y con el valor 0 si vale
.
n-simo bit contribuye al resultado con el valor 2n1 si vale
Pero, ojo!, cuando decimos n-simo bit, no nos referimos al n-simo carcter de la cadena. Por
tiene su tercer bit a 1, pero ese es el carcter que ocupa la primera
ejemplo, la cadena
posicin de la cadena (la que tiene ndice 0), no la tercera. Podemos recorrer la cadena de
izquierda a derecha e ir llevando la cuenta del nmero de bit actual en una variable:
1
2
3
4
5
6
7
8
9

10

bits

input

n
len bits
valor
0
for bit in bits
if bit
valor
n
1
print

valor

n 1

valor

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

171
1
2
3
4
5
6
7
8
9

10

172

bits

Haz una traza para las cadenas

Una vez ms, nuestro aprendiz ha diseado un programa diferente:

input

valor
0
for bit in bits
if bit
valor
else
valor
print

valor

valor

valor

Es correcto? Haz trazas para las cadenas

1
2
3
4
5
6
7
8
9

10

173

bits

print

3
4
5
6
7

bits

valor
valor

1
valor

Y esta otra? Es correcta?

input

valor
0
for bit in bits
valor
valor
print

input

Haz trazas para las cadenas

Y esta otra versin? Es correcta?

valor
0
for bit in bits
if bit
valor
else
valor

174

int bit

Haz trazas para las cadenas

valor

175
Qu pasa si introducimos una cadena con caracteres que no pertenecen al conjunto
de dgitos binarios como, por ejemplo,
? Modifica el programa para que, en tal caso,
y solicite nuevamente la
muestre en pantalla el mensaje
introduccin de la cadena.
176
Disea un programa que convierta una cadena de dgitos entre el y el al
valor correspondiente a una interpretacin de dicha cadena como nmero en base octal.

177
Disea un programa que convierta una cadena de dgitos o letras entre la y
la al valor correspondiente a una interpretacin de dicha cadena como nmero en base
hexadecimal.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

178
Disea un programa que reciba una cadena que codifica un nmero en octal, decimal
o hexadecimal y muestre el valor de dicho nmero. Si la cadena empieza por o se
es 255); si no, si empieza por
interpretar como un nmero hexadecimal (ejemplo:
es 15); y si no, se
o , la cadena se interpretar como un nmero octal (ejemplo:
es 99).
interpretar como un nmero decimal (ejemplo:

179
Disea un programa que lea un nmero entero y muestre una cadena con su representacin octal.

180
Disea un programa que lea una cadena que representa un nmero codificado en
base 8 y muestre por pantalla su representacin en base 2.

5.1.8.

A vueltas con las cadenas: inversin de una cadena

Recuerda del captulo 2 que el operador puede trabajar con cadenas y denota la operacin
de concatenacin, que permite obtener la cadena que resulta de unir otras dos:

Vamos a utilizar este operador en el siguiente ejemplo: un programa que lee una cadena y
muestra su inversin en pantalla. El programa se ayudar de una cadena auxiliar, inicialmente
vaca, en la que iremos introduciendo los caracteres de la cadena original, pero de atrs hacia
adelante.
1
2
3
4
5
6
7

cadena

input

inversin
for carcter in cadena
inversin
carcter
print

Probemos el programa:

inversin

inversin

181
Una palabra es alfabtica si todas sus letras estn ordenadas alfabticamente. Por
ejemplo,
,
e
son palabras alfabticas. Disea un programa que lea
una palabra y nos diga si es alfabtica o no.

182
Disea un programa que nos diga si una cadena es palndromo o no. Una cadena
es palndromo si se lee igual de izquierda a derecha que de derecha a izquierda. Por ejemplo,
es un palndromo.

183
Una frase es palndromo si se lee igual de izquierda a derecha que de derecha a
izquierda, pero obviando los espacios en blanco y los signos de puntuacin. Por ejemplo, las ca,
,
y
denas
contienen frases palndromas. Disea un programa que diga si una frase es o no es palndroma.

184
Probablemente el programa que has diseado para el ejercicio anterior falle ante
frases palndromas como estas: Dbale arroz a la zorra el abad, Salta Lenn el atlas, Amigo,
no gima, tale, demonaco Can, o me delata, Ans us tu auto, Susana, A Mercedes, ese
de crema, A mam Roma le aviva el amor a pap, y a pap Roma le aviva el amor a mam
y arriba la birra!, pues hemos de comparar ciertas letras con sus versiones acentuadas, o
maysculas o la apertura de exclamacin con su cierre. Modifica tu programa para que identifique correctamente frases palndromas en las que pueden aparecer letras maysculas, vocales
acentuadas y la vocal u con diresis.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

185
Hay un tipo de pasatiempos que propone descifrar un texto del que se han suprimido
, se descifra sustituyendo
las vocales. Por ejemplo, el texto
. Disea
cada punto con una vocal del texto. La solucin es
un programa que ayude al creador de pasatiempos. El programa recibir una cadena y mostrar
otra en la que cada vocal ha sido reemplazada por un punto.
186
El nombre de un fichero es una cadena que puede tener lo que denominamos una
extensin. La extensin de un nombre de fichero es la serie de caracteres que suceden al ltimo
punto presente en la cadena. Si el nombre no tiene ningn punto, asumiremos que su extensin
es la cadena vaca. Haz un programa que solicite el nombre de un fichero y muestre por pantalla
los caracteres que forman su extensin. Prueba la validez de tu programa pidiendo que muestre
la extensin de los nombres de fichero
y
, que son
y
,
respectivamente.

187
Haz un programa que lea dos cadenas que representen sendos nmeros binarios. A
continuacin, el programa mostrar el nmero binario que resulta de sumar ambos (y que ser
y
, el programa
otra cadena). Si, por ejemplo, el usuario introduce las cadenas
.
mostrar como resultado la cadena
(Nota: El procedimiento de suma con acarreo que implementes deber trabajar directamente
con la representacin binaria leda).

188
Una de las tcnicas de criptografa ms rudimentarias consiste en sustituir cada uno
de los caracteres por otro situado n posiciones ms a la derecha en el abecedario. Si n = 2,
por ejemplo, sustituiremos la a por la c, la b por la d, y as sucesivamente. El problema
que aparece en las ltimas n letras del alfabeto tiene fcil solucin: en el ejemplo, la letra
y se sustituir por la a y la letra z por la b. La sustitucin debe aplicarse a las letras
minsculas y maysculas y a los dgitos (el 0 se sustituye por el 2, el 1 por el 3 y as
hasta llegar al 8, que se sustituye por el 0, y el 9, que se sustituye por el 1).
Disea un programa que lea un texto y el valor de n y muestre su versin criptografiada.
189
Disea un programa que lea un texto criptografiado siguiendo la tcnica descrita en
el apartado anterior y el valor de n utilizado al encriptar para mostrar ahora el texto decodificado.

5.1.9.

Subcadenas: el operador de corte

Desarrollemos un ltimo ejemplo: un programa que, dados una cadena y dos ndices i y j,
muestra la (sub)cadena formada por todos los caracteres entre el que tiene ndice i y el que
tiene ndice j, incluyendo al primero pero no al segundo.
La idea bsica consiste en construir una nueva cadena que, inicialmente, est vaca. Con
un recorrido por los caracteres comprendidos entre los de ndices i y j 1 iremos aadiendo
caracteres a la cadena. Vamos con una primera versin:
1
2
3
4
5
6
7
8
9

cadena
input
i
int input
j
int input

subcadena
for k in range i
subcadena
print

j
cadena k

Usmosla:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

format i

subcadena

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Falla algo en nuestro programa? S: es fcil cometer un error de indexacin. Por ejemplo, al
y los ndices 3 y 20 se cometer un error, pues
ejecutar el programa con la cadena
20 es mayor que la longitud de la cadena. Corrijamos ese problema:
1
2
3
4
5
6
7
8
9

10
11
12
13
14

cadena
input
i
int input
j
int input
if j

else

len cadena
final
len cadena
final

subcadena
for k in range i
subcadena
print

final
cadena k

format i

subcadena

190
Y si se introduce un valor de i negativo? Corrige el programa para que detecte esa
posibilidad e interprete un ndice inicial negativo como el ndice 0.

191
No ser tambin problemtico que introduzcamos un valor del ndice i mayor o igual
que el de j? Se producir entonces un error de ejecucin? Por qu?

192
Disea un programa que, dados una cadena c, un ndice i y un nmero n, muestre la
subcadena de c formada por los n caracteres que empiezan en la posicin de ndice i.

Hemos visto cmo construir una subcadena carcter a carcter. Esta es una operacin frecuente en los programas que manejan informacin textual, as que Python ofrece un operador
predefinido que facilita esa labor: el operador de corte (en ingls, slicing operator). La notacin
es un tanto peculiar, pero cmoda una vez te acostumbras a ella. Fjate en este ejemplo:

El operador de corte se denota con dos puntos ( ) que separan dos ndices dentro de los
corchetes del operador de indexacin. La expresin a i j significa que se desea obtener la
subcadena formada por los caracteres a i , a i 1 , . . . , a j 1 , (observa que, como en range, el
valor del ltimo ndice se omite).
Ya que se omite el ltimo ndice del corte, puede que te resulte de ayuda imaginar que los
ndices de los elementos se disponen en las fronteras entre elementos consecutivos, como se
puede ver en esta figura:
0

-7

-6

-5

-4

-3

-2

-1

Ah queda claro que a 2 5 , a 5 5 , a 2


2 y a 5 2 , siendo a la cadena de la
.
figura, es la cadena
Cada ndice de corte tiene un valor por defecto, as que puedes omitirlo si te conviene. El
corte a j es equivalente a a 0 j y el corte a i equivale a a i len a .
193

Si a vale

, qu es el corte a

194
Qu corte utilizaras para obtener los n caracteres de una cadena a partir de la
posicin de ndice i?

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

195
Disea un programa que, dada una cadena, muestre por pantalla todos sus prefijos.
, por pantalla debe aparecer:
Por ejemplo, dada la cadena
196
Disea un programa que lea una cadena y muestre por pantalla todas sus subcadenas
de longitud 3.

197
Disea un programa que lea una cadena y un entero k y muestre por pantalla todas
sus subcadenas de longitud k.
no.

198

Disea un programa que lea dos cadenas a y b y nos diga si b es un prefijo de a o

(Ejemplo:

es un prefijo de

).

199
Disea un programa que lea dos cadenas a y b y nos diga si b es una subcadena
de a o no.
es una subcadena de
).
(Ejemplo:

200
Disea un programa que lea dos cadenas y devuelva el prefijo comn ms largo de
ambas.
y
tienen como prefijo comn ms
(Ejemplo: las cadenas
).
largo a la cadena

201
Disea un programa que lea tres cadenas y muestre el prefijo comn ms largo de
todas ellas.
,
y
tienen como prefijo
(Ejemplo: las cadenas
).
comn ms largo a la cadena
Cortes avanzados

Desde la versin 2.3, Python entiende una forma extendida de los cortes. Esta forma acepta tres
valores separados por el carcter :. El tercer valor equivale al tercer parmetro de la funcin range:
indica el incremento del ndice en cada iteracin. Por ejemplo, si c contiene la cadena
,
el corte c 0 len c 2 selecciona los caracteres de ndice par, o sea, devuelve la cadena
.
El tercer valor puede ser negativo. Ello permite invertir una cadena con una expresin muy sencilla:
c
1 . Haz la prueba.

5.1.10.

Una aplicacin: correo electrnico personalizado

Vamos a desarrollar un programa til: uno que enva textos personalizados por correo
electrnico. Deseamos enviar una carta tipo a varios clientes, pero adaptando algunos datos de
la misma a los propios de cada cliente. Aqu tienes un ejemplo de carta tipo:
Deseamos sustituir las marcas , y por el tratamiento (seor o seora), el
apellido y la deuda, respectivamente, de cada cliente y enviarle el mensaje resultante por correo
electrnico. Nuestro programa pedir los datos de un cliente, personalizar el escrito, se lo
enviar por correo electrnico y a continuacin, si lo deseamos, repetir el proceso para un
nuevo cliente.
Antes de empezar a desarrollar el programa nos detendremos para aprender lo bsico del
mdulo smtplib, que proporciona funciones para usar el protocolo de envo de correo electrnico

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

SMTP (siglas de Simple Mail Transfer Protocol, o sea, Protocolo Sencillo de Transferencia
de Correo)1 . Lo mejor ser que estudiemos un ejemplo de uso de la librera y que analicemos
lo que hace paso a paso.
1
2
3
4
5
6
7
8
9

10

from smtplib import SMTP


servidor
SMTP
remitente
destinatario
mensaje
mensaje
mensaje

servidor sendmail remitente

Cambia la cadena por el nombre de tu servidor.

format remitente
destinatario

destinatario

mensaje

Vamos por partes. La primera lnea importa la funcin SMTP del mdulo smtplib. La lnea 3
crea una conexin con la mquina servidora (va la llamada a SMTP), que en nuestro ejemplo
, y devuelve un objeto que guardamos en la variable servidor. Las lneas 4
es
y 5 guardan las direcciones de correo del remitente y del destinatario en sendas variables,
mientras que las tres lneas siguientes definen el mensaje que vamos a enviar. As, la lnea 6
define las denominadas cabeceras (headers) del correo y son obligatorias en el protocolo
SMTP (respetando, adems, los saltos de lnea que puedes apreciar al final de las cadenas).
Las dos lneas siguientes constituyen el mensaje en s mismo. Finalmente, la ltima lnea se
encarga de efectuar el envo del correo a travs de la conexin almacenada en servidor y
el mtodo sendmail. Eso es todo. Si ejecutamos el programa y tenemos permiso del servidor,
recibir un correo de
con el texto que
hemos almacenado en mensaje.
Nuestro programa presentar el siguiente aspecto:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21

from smtplib import SMTP


servidor
remitente
texto
texto
texto
texto

SMTP

seguir
while seguir
destinatario
input
tratamiento
input
apellido
input
euros
input
mensaje
mensaje

texto personalizado

servidor sendmail remitente


seguir
input

destinatario

format remitente
mensaje

destinatario

En la lnea 18 hemos dejado un fragmento de programa por escribir: el que se encarga de


personalizar el contenido de texto con los datos que ha introducido el usuario. Cmo personalizamos el texto? Deberamos ir copiando los caracteres de texto uno a uno en una variable

1 No pierdas de vista que el objetivo de esta seccin es aprender el manejo de cadenas. No te despistes tratando de
profundizar ahora en los conceptos del SMTP y las peculiaridades del correspondiente mdulo.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

auxiliar (inicialmente vaca) hasta ver el carcter , momento en el que deberemos estudiar el
siguiente carcter y, en funcin de cul sea, aadir el contenido de tratamiento, apellido o euros.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

from smtplib import SMTP


servidor
remitente
texto
texto
texto
texto

SMTP

seguir
while seguir
destinatario
input
tratamiento
input
apellido
input
euros
input

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

202
vale

mensaje

personalizado
i
0
while i
len texto
if texto i
personalizado
texto i
else
if texto i 1
personalizado
apellido
i
i
1
elif texto i 1
personalizado
euros
i
i
1
elif texto i 1
personalizado
tratamiento
i
i
1
else
personalizado
i
i
1
mensaje
personalizado
servidor sendmail remitente
seguir
input

5.1.11.

destinatario

format remitente

mensaje

destinatario

El programa no funcionar bien con cualquier carta. Por ejemplo, si la variable texto
el programa falla. Por qu? Sabras corregir el programa?

Referencias a cadenas

En el apartado 2.4 hemos representado las variables y su contenido con diagramas de cajas.
Por ejemplo, las siguientes asignaciones:

conducen a una disposicin de la informacin en la memoria que mostramos grficamente as:


a

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

3.25
Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Buscando texto en cadenas

Estudiamos los aspectos fundamentales de las cadenas y montamos a mano las operaciones
ms sofisticadas. Por ejemplo, hemos estudiado la indexacin y la utilizamos, en combinacin con un
bucle, para buscar un carcter determinado en una cadena. Pero esa es una operacin muy frecuente,
as que Python la trae de serie.
El mtodo find recibe una cadena y nos dice si esta aparece o no en la cadena sobre la que
se invoca. Si est, nos devuelve el ndice de su primera aparicin. Si no est, devuelve el valor 1.
Atencin a estos ejemplos:

til, no? Pues hay muchos ms mtodos que permiten realizar operaciones complejas con enorme facilidad. Encontrars, entre otros, mtodos para sustituir un fragmento de texto por otro, para
saber si todos los caracteres son minsculas (o maysculas), para saber si empieza o acaba con un
texto determinado, etc. Cuantos ms mtodos avanzados conozcas, ms productivo sers. Que dnde
encontrars la relacin de mtodos? En la documentacin de Python. Acostmbrate a manejarla.

Decimos que a apunta al valor 2 y que b apunta al valor 3.25. La flecha recibe el nombre
de puntero o referencia.
Con las cadenas representaremos los valores desglosando cada uno de sus caracteres en una
caja individual con un ndice asociado. El resultado de una asignacin como esta:

se representar del siguiente modo:


c

Decimos que la variable c apunta a la cadena


, que es una secuencia de
caracteres.
La cadena vaca no ocupa ninguna celda de memoria y la representamos grficamente de un
modo especial. Una asignacin como esta:

se representar del siguiente modo:

Que las variables contengan referencias a los datos y no los propios datos es muy til para
aprovechar la memoria del ordenador. El siguiente ejemplo te ilustrar el ahorro que se consigue.
Tras ejecutar la primera accin tenemos:
a

Y despus de ejecutar la segunda:


a

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Las referencias son direcciones de memoria (I)

Vamos a darte una interpretacin de las referencias que, aunque constituye una simplificacin de
la realidad, te permitir entender qu son. Ya dijimos en el captulo 1 que la memoria del computador
se compone de una serie de celdas numeradas con sus direcciones. En cada celda cabe un escalar. La
cadena
ocupa cuatro celdas, una por cada carcter. Por otra parte, una variable solo puede
contener un escalar. Como la direccin de memoria es un nmero y, por tanto, un escalar, el truco
consiste en almacenar en la variable la direccin de memoria en la que empieza la cadena. Fjate
en este ejemplo en el que una variable ocupa la direccin de memoria 1000 y contiene la cadena
:
1000
1001
2100
2101
2102
2103

..
.
2100

..
.
..
.

Como puedes ver, en realidad la cadena ocupa posiciones consecutivas a partir de una direccin
determinada (en el ejemplo, la 2100) y la variable contiene el valor de dicha referencia. La flecha de
los diagramas hace ms legibles las referencias:
1000
1001
2100
2101
2102
2103

..
.
2100

..
.
..
.

Tanto a como b apuntan a la misma cadena! Al asignar a una variable la cadena contenida
en otra nicamente se copia su referencia y no cada uno de los caracteres que la componen.
Si se hiciera del segundo modo, la memoria ocupada y el tiempo necesarios para la asignacin
seran tanto mayores cuanto ms larga fuera la cadena. El mtodo escogido nicamente copia
el valor de la referencia, as que es independiente de la longitud de la cadena (y prcticamente
instantneo).
Has de tener en cuenta, pues, que una asignacin nicamente altera el valor de un puntero.
Pero otras operaciones con cadenas comportan la reserva de nueva memoria. Tomemos por caso
el operador de concatenacin. La concatenacin toma dos cadenas y forma una cadena nueva
que resulta de unir ambas, es decir, reserva memoria para una nueva cadena. Veamos paso a
paso cmo funciona el proceso con un par de ejemplos. Fjate en estas sentencias:

as:

Podemos representar grficamente el resultado de la ejecucin de las dos primeras sentencias


a

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Las referencias son direcciones de memoria (y II)

Veamos qu ocurre cuando dos variables comparten referencia. El ejemplo que hemos desarrollado
en el texto estudia el efecto de estas dos asignaciones:
Como vimos antes, la primera asignacin conduce a esta situacin:
..
.
2100

1000
1001

..
.

2100
2101
2102
2103

Pues bien, la segunda asignacin copia en la direccin de b (que suponemos es la 1001) el valor
que hay almacenado en la direccin de a, es decir, el valor 2100:
..
.
2100
2100
..
.

1000
1001
2100
2101
2102

a
b

2103

Copiar un valor escalar de una posicin de memoria a otra es una accin muy rpida.

Analicemos ahora la tercera sentencia. Primero, Python evala la expresin a


b, as que
reserva un bloque de memoria con espacio para 11 caracteres y copia en ellos los caracteres de
a seguidos de los caracteres de b:
a

10

Y ahora que ha creado la nueva cadena, se ejecuta la asignacin en s, es decir, se hace que
c apunte a la nueva cadena:
a

b
c

10

El orden en el que ocurren las cosas tiene importancia para entender cmo puede verse afectada
la velocidad de ejecucin de un programa por ciertas operaciones. Tomemos por caso estas dos
rdenes:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

A simple vista parece que la primera sentencia ser ms lenta en ejecucin que la segunda,
pues comporta la reserva de una zona de memoria que puede ser grande (imagina si la cadena
tuviera mil o incluso cien mil caracteres), mientras que la segunda sentencia se limita a aadir
un solo carcter. Pero no es as: ambas tardan casi lo mismo. Veamos cul es la razn. La primera
sentencia reserva memoria para 24 caracteres, los guarda en ella y hace que a apunte a dicha
zona:
0

10

11

12

13

14

15

16

17

18

19

20

21

22

23

Y ahora veamos paso a paso qu ocurre al ejecutar la segunda sentencia. En primer lugar,
se evala la parte derecha, es decir, se reserva espacio para 25 caracteres y se copian en l los
24 caracteres de a y el carcter punto:
a

10

11

12

13

14

15

16

17

18

19

20

21

22

23

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

Y ahora, al ejecutar la asignacin, la variable a deja de apuntar a la zona de memoria original


para apuntar a la nueva zona de memoria:
a

10

11

12

13

14

15

16

17

18

19

20

21

22

23

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

Como la zona inicial de memoria ya no se usa para nada, Python la libera, es decir, considera
que est disponible para futuras operaciones, con lo que, a efectos prcticos, desaparece:
a

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

Como puedes ver, la sentencia que consiste en aadir un simple punto a una cadena es ms
costosa en tiempo que la que comporta una asignacin a una variable de esa misma cadena.
El operador con asignacin
acta exactamente igual con cadenas, as que sustituir la
presenta el mismo problema.
ltima sentencia por a
El operador de corte tambin reserva una nueva zona de memoria:
a

203

Dibuja un diagrama con el estado de la memoria tras ejecutar estas sentencias:

204
Dibuja diagramas que muestren el estado de la memoria paso a paso para esta
secuencia de asignaciones.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Qu se mostrar por pantalla si imprimimos a, b y c al final?

5.2.

Listas

El concepto de secuencia es muy potente y no se limita a las cadenas. Python nos permite
definir secuencias de valores de cualquier tipo. Por ejemplo, podemos definir secuencias de
nmeros enteros o flotantes, o incluso de cadenas. Hablamos entonces de listas. En una lista
podemos, por ejemplo, registrar las notas de los estudiantes de una clase, la evolucin de la
temperatura hora a hora, los coeficientes de un polinomio, la relacin de nombres de personas
asistentes a una reunin, etc.
Python sigue una notacin especial para representar las listas. Los valores de una lista deben
estar encerrados entre corchetes y separados por comas. He aqu una lista con los nmeros del
1 al 3:
Podemos asignar listas a variables:
Los elementos que forman una lista tambin pueden ser cadenas.

Y tambin podemos usar expresiones para calcular el valor de cada elemento de una lista:
Python almacena las listas del mismo modo que las cadenas: mediante referencias (punteros)
a la secuencia de elementos. As, el ltimo ejemplo hace que la memoria presente un aspecto
como el que muestra el siguiente diagrama:
0

1 2 3

1 2 3

La asignacin a una variable del contenido de otra variable que almacena una (referencia a
una) lista supone la copia de, nicamente, su referencia, as que ambas acaban apuntando a la
misma zona de memoria:

La lista que contiene un solo elemento presenta un aspecto curioso:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Observa que no es lo mismo 10 que 10. 10 es la lista cuyo nico elemento es el entero 10,
y 10 es un entero. Grficamente hemos destacado la lista disponiendo encima de la celda su
ndice. Si pedimos a Python que nos muestre el contenido de las variables a y b, veremos que
la representacin de la lista que contiene un escalar y la del escalar son diferentes:
La lista siempre se muestra encerrada entre corchetes.
Del mismo modo que hay una cadena vaca, existe tambin una lista vaca. La lista vaca se
denota as:
y la representamos grficamente como la cadena vaca:

5.2.1.

Cosas que, sin darnos cuenta, ya sabemos sobre las listas

Una ventaja de Python es que proporciona operadores y funciones similares para trabajar con
tipos de datos similares. Las cadenas y las listas tienen algo en comn: ambas son secuencias
de datos, as pues, muchos de los operadores y funciones que trabajan sobre cadenas tambin
lo hacen sobre listas. Por ejemplo, la funcin len, aplicada sobre una lista, nos dice cuntos
elementos la integran:

La longitud de la lista vaca es 0:


El operador

y el operador

concatena listas:

repite un nmero dado de veces una lista:

Has de tener en cuenta que tanto


Observa este ejemplo:

como

generan nuevas listas, sin modificar las originales.

La memoria queda as:


Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1 2 3

1 2 3 4

b
c

Ves? La asignacin a b deja intacta la lista a porque apunta al resultado de concatenar


algo a a. La operacin de concatenacin no modifica la lista original: reserva memoria para una
nueva lista con tantos elementos como resultan de sumar la longitud de las listas concatenadas
y, a continuacin, copia los elementos de la primera lista seguidos por los de la segunda lista
en la nueva zona de memoria. Como asignamos a b el resultado de la concatenacin, tenemos
que b apunta a la lista recin creada. La tercera sentencia es una simple asignacin a c, as que
Python se limita a copiar la referencia.
El operador de indexacin tambin es aplicable a las listas:

A veces, el operador de indexacin puede dar lugar a expresiones algo confusas a primera
vista:
En este ejemplo, el primer par de corchetes indica el principio y final de la lista (formada
por el 1, el 2 y el 3) y el segundo par indica el ndice del elemento al que deseamos acceder
(el primero, es decir, el de ndice 0).
205
Qu aparecer por pantalla al evaluar la expresin 1
0 ?
sin

0 ? Y al evaluar la expre-

De todos modos, no te preocupes por esa notacin un tanto confusa: lo normal es que accedas
a los elementos de listas que estn almacenadas en variables, con lo que rara vez tendrs dudas.
Tambin el operador de corte es aplicable a las listas:

Has de tener en cuenta que un corte siempre se extrae copiando un fragmento de la lista, por
lo que comporta la reserva de memoria para crear una nueva lista. Analiza la siguiente secuencia
de acciones y sus efectos sobre la memoria:
a

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

1 2 3 4 5

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1 2 3 4 5

2 3

1 2 3 4 5

2 3

1 2 3 4 5

2 3

1 2 3 4 5

Si deseas asegurarte de que trabajas con una copia de una lista y no con la misma lista (a
travs de una referencia) utiliza el operador de corte en la asignacin.
206
Hemos asignado a x la lista 1 2
x
, pero parece que y
Podramos hacer y

3 y ahora queremos asignar a y una copia.


x
tambin funciona. Es as? Por qu?

El iterador for in tambin recorre los elementos de una lista:

De hecho, ya hemos utilizado bucles que recorren secuencias de valores:

Recuerda que puedes combinar las funciones list y range para construir cmodamente una
lista de valores:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Una forma corriente de construir listas que contienen rplicas de un mismo valor se ayuda
del operador . Supongamos que necesitamos una lista de 10 elementos, todos los cuales valen 0.
Podemos hacerlo as:

1
2
3
4

1
2

207

Qu aparecer por pantalla al ejecutar este programa?

208

Qu aparecer por pantalla al ejecutar este programa?

print
for i in
print
print

for i in 1
print i

5.2.2.

10

Comparacin de listas

Los operadores de comparacin tambin trabajan con listas. Parece claro cmo se comportarn
operadores como el de igualdad ( ) o el de desigualdad ( ):
si las listas son de talla diferente, resolviendo que las listas son diferentes;

y si miden lo mismo, comparando elemento a elemento de izquierda a derecha y resolviendo


que las dos listas son iguales si todos sus elementos son iguales, y diferentes si hay algn
elemento distinto.

Hagamos un par de pruebas con el intrprete de Python:

Los operadores , ,
y
tambin funcionan con listas. Cmo? Del mismo modo que
con las cadenas, pues al fin y al cabo, tanto cadenas como listas son secuencias. Tomemos, por
ejempo, el operador al comparar las listas 1 2 3 y 1 3 2 , es decir, al evaluar la
1 3 2 . Se empieza por comparar los primeros elementos de ambas
expresin 1 2 3
listas. Como no es cierto que 1
1, pasamos a comparar los respectivos segundos elementos.
3, el resultado es True, sin necesidad de efectuar ninguna comparacin adicional.
Como 2
209

Sabras decir que resultados se mostrarn al ejecutar estas sentencias?

210
Disea un programa que tras asignar dos listas a sendas variables nos diga si la
primera es menor que la segunda. No puedes utilizar operadores de comparacin entre listas
para implementar el programa.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5.2.3.

El operador is

Hemos visto que las listas conllevan una forma de reservar memoria curiosa: en ocasiones,
dos variables apuntan a una misma zona de memoria y en ocasiones no, incluso cuando los datos
de ambas variables son idnticos. Fjate en este ejemplo:
Ya hemos visto que, tras efectuar las asignaciones, la memoria quedar as:
a

b
c

1 2 3

1 2 3

Qu ocurre si comparamos entre s los diferentes elementos?

Efectivamente: siempre dice que se trata de listas iguales, y es cierto. S, pero, no son
ms iguales las listas a y c que las listas a y b? A fin de cuentas, tanto a como c apuntan
exactamente a la misma zona de memoria, mientras que b apunta a una zona distinta. Python
dispone de un operador de comparacin especial que an no te hemos presentado: is (en espaol,
es). El operador is devuelve True si dos objetos son en realidad el mismo objeto, es decir, si
residen ambos en la misma zona de memoria, y False en caso contrario.

plo:

Python reserva nuevos bloques de memoria conforme evala expresiones. Observa este ejem-

La segunda orden compara la lista almacenada en a, que se cre al evaluar una expresin
en la orden anterior, con la lista 1 2 que se crea en ese mismo instante, as que is nos dice
sigue devolviendo el valor True,
que ocupan posiciones de memoria diferentes. El operador
pues aunque sean objetos diferentes son equivalentes elemento a elemento.
211

Qu ocurrir al ejecutar estas rdenes Python?

212
Explica, con la ayuda de un grfico que represente la memoria, los resultados de
evaluar estas expresiones:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

213

Qu ocurrir al ejecutar estas rdenes Python?

214

Qu se muestra por pantalla como respuesta a cada una de estas sentencias Python?

5.2.4.

Modificacin de elementos de listas

Hasta el momento hemos aprendido a crear listas y a consultar su contenido, bien accediendo
a uno cualquiera de sus elementos (mediante indexacin), bien recorriendo todos sus elementos
(con un bucle for in). En este apartado veremos cmo modificar el contenido de las listas.
Podemos asignar valores a elementos particulares de una lista gracias al operador de indexacin:
0

1 2 3

1 10 3

Cada celda de una lista es, en cierto modo, una variable autnoma: podemos almacenar en
ella un valor y modificarlo a voluntad.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

215
Haz un programa que almacene en una variable a la lista obtenida mediante
list range 1 4 y, a continuacin, la modifique para que cada componente sea igual al cuadrado del componente original. El programa mostrar la lista resultante por pantalla.

216
Haz un programa que almacene en a una lista obtenida con list range 1 n , donde
n es un entero que se pide al usuario, y modifique dicha lista para que cada componente sea
igual al cuadrado del componente original. El programa mostrar la lista resultante por pantalla.

217
Haz un programa que, dada una lista a cualquiera, sustituya cualquier elemento
negativo por cero.
1
2
3
4
5
6
7
8
9

10
11

218

Qu mostrar por pantalla el siguiente programa?

a
list range 0 5
b
list range 0 5
c
a
d
b
e
a
b
f
b 1
g
b 0
c 0
100
d 0
200
e 0
300
print a b c d e

Comprueba con el ordenador la validez de tu respuesta.

5.2.5.

Mutabilidad, inmutabilidad y representacin de la informacin en


memoria

Python procura no consumir ms memoria que la necesaria. Ciertos objetos son inmutables, es
decir, no pueden modificar su valor. El nmero 2 es siempre el nmero 2. Es un objeto inmutable.
Python procura almacenar en memoria una sola vez cada valor inmutable. Si dos o ms variables
contienen ese valor, sus referencias apuntan a la misma zona de memoria. Considera este ejemplo:
La memoria presenta, tras esas asignaciones, este aspecto:
a

Y qu ocurre cuando modificamos el valor de una variable inmutable? No se modifica el


contenido de la caja que contiene el valor, sino que el correspondiente puntero pasa a apuntar
a una caja con el nuevo valor; y si esta no existe, se crea.
Si a las asignaciones anteriores les sigue una ms:
la memoria pasa a tener este aspecto:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

2
3
Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Tambin las cadenas Python son objetos inmutables2 . Que lo sean tiene efectos sobre las
operaciones que podemos efectuar con ellas. La asignacin a un elemento de una cadena, por
ejemplo, est prohibida, as que Python la seala con un error de tipo (TypeError):

Las listas se comportan de forma diferente: a diferencia de las cadenas, son mutables. De
momento te hemos proporcionado una representacin de las listas excesivamente simplifica1 2 1 como se muestra a la
da. Hemos representando el resultado de la asignacin a
izquierda, cuando lo correcto sera hacerlo como se muestra a la derecha:
a

1 2 1

La realidad, como ves, es algo complicada: la lista almacena referencias a los valores, y no los
propios valores. Pero an no lo has visto todo. Qu ocurre tras ejecutar estas sentencias?
Nada menos que esto:

a
b
c

Como habrs observado, para cada aparicin de un literal de lista, es decir, de una lista
expresada explcitamente, (como 1 2 1 ), Python ha reservado nueva memoria, aunque exista
1 2 1 yc
1 2 1 han generado sendas
otra lista de idntico valor. As pues, a
reservas de memoria y cada variable apunta a una zona de memoria diferente. Como el contenido
de cada celda ha resultado ser un valor inmutable (un entero), se han compartido las referencias
a los mismos. El operador is nos ayuda a confirmar nuestra hiptesis:

Modifiquemos ahora el contenido de una celda de una de las listas:

2 Aunque

los ejemplos que hemos presentado con enteros no son directamente trasladables al caso de las cadenas.
Aunque parezca paradjico, Python puede decidir por razones de eficiencia que dos cadenas con idntico contenido se
almacenen por duplicado.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

El resultado es este:

a
b

219
naciones:

Representa el estado de la memoria tras efectuar cada una de las siguientes asig-

Aunque los diagramas que hemos mostrado responden a la realidad, usaremos normalmente
su versin simplificada (y, en cierto modo, falsa), pues es suficiente para el diseo de la mayor
parte de programas que vamos a presentar. Con esta visin simplificada, la ltima figura se
representara as:
1

1 2 1

1 2 3

5.2.6.

Adicin de elementos a una lista

Podemos aadir elementos a una lista, esto es, hacerla crecer. Cmo? Una idea que parece
(siendo a una variable que
natural, pero que no funciona, es asignar un valor a a len a
contiene una lista), pues de algn modo estamos sealando una posicin ms a la derecha del
ltimo elemento. Python nos indicar que estamos cometiendo un error:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Una idea mejor consiste en utilizar el operador :

Algo ha ido mal. Claro!, el operador de concatenacin trabaja con dos listas, no con una
lista y un entero, as que el elemento a aadir debe formar parte de una lista. . . aunque esta
solo tenga un elemento:

Existe otro modo efectivo de aadir elementos a una lista: mediante el mtodo append (que
en ingls significa aadir). Observa cmo usamos append:

Hay una diferencia fundamental entre usar el operador de concatenacin y usar append:
la concatenacin crea una nueva lista copiando los elementos de las listas que participan como
operandos y append modifica la lista original. Observa qu ocurre paso a paso en el siguiente
ejemplo:
0

1 2 3

1 2 3

1 2 3 4

1 2 3

b
c

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

1 2 3 4

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

b
c

1 2 3

1 2 3 4 5

Por qu complicarse la vida con append, cuando la concatenacin hace lo mismo y nos
asegura trabajar con una copia de la memoria? Por eficiencia: es ms eficiente hacer append
que concatenar. Concatenar supone crear una lista nueva en la que se copian todos y cada uno
de los elementos de las listas concatenadas. Es decir, la concatenacin del siguiente ejemplo
supone la copia de 1001 elementos (los 1000 de la lista original y el que aadimos):
Sin embargo, el append de este otro ejemplo equivalente trabaja sobre la lista original y le
aade una celda cuyo contenido es 0:3

En este ejemplo, pues, el append ha resultado unas 1000 veces ms eficiente que la concatenacin.
Desarrollemos un ejemplo prctico. Vamos a escribir un programa que construya una lista
con todos los nmeros primos entre 1 y n. Como no sabemos a priori cuntos hay, construiremos
una lista vaca e iremos aadiendo nmeros primos conforme los vayamos encontrando.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15

int input

primos
for nmero in range 2 n 1
Determinamos si nmero es primo.
creo_que_es_primo
True
for divisor in range 2 nmero
if nmero
divisor
0
creo_que_es_primo
False
break
Y si es primo, lo aadimos a la lista.
if creo_que_es_primo
primos append nmero
print primos

220
Disea un programa que construya una lista con los n primeros nmeros primos
(ojo: no los primos entre 1 y n, sino los n primeros nmeros primos). Necesitas usar append?
Puedes reservar en primer lugar una lista con n celdas nulas y asignarle a cada una de ellas
uno de los nmeros primos?
3 No siempre es ms eficiente aadir que concatenar. Python puede necesitar memoria para almacenar la lista
resultante de aadir un elemento y, entonces, ha de efectuar una copia del contenido de la lista. Pero esto supone entrar
en demasiado detalle para el nivel de este texto.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5.2.7.

Lectura de listas por teclado

Hasta el momento hemos aprendido a construir listas de diferentes modos, pero nada hemos
dicho acerca de cmo leer listas desde el teclado. La funcin que lee de teclado es input,
funcionar tambin con listas?
E
1
2

lista
input
print lista

Ha funcionado? No. Lo que se ha ledo es una cadena, no una lista. Podemos cerciorarnos
; o
accediendo a su primer elemento: si fuera una lista, valdra 1 y si fuera una cadena,
inquiriendo por su longitud: si fuera una lista valdra 3 y si fuera una cadena valdra 9:
E
1
2
3
4

lista
input
print lista
print lista 0
print len lista

De todos modos, era previsible, pues ya dijimos en su momento que input devolva una cadena.
Cuando queramos obtener, por ejemplo, un entero, encerrbamos la llamada a input con una
llamada a la funcin int y cuando queramos un flotante, con float. Habr alguna funcin similar
para obtener listas? Si queremos una lista, lo lgico sera utilizar una llamada a list, que en
ingls significa lista:
E
1
2

lista
list input
print lista

Oh, oh! Tenemos una lista, s, pero no la que esperbamos:


0

La funcin list devuelve una lista a partir de una cadena, pero cada elemento de la lista es
un carcter de la cadena (por ejemplo, el que ocupa la posicin de ndice 4 no es el entero 2,
sino el carcter ). No se interpreta, pues, como hubiramos deseado, es decir, como esta lista
de nmeros enteros:
a

1 2 3

Para leer listas deberemos utilizar un mtodo distinto. Lo que haremos es ir leyendo la lista
elemento a elemento y construir la lista paso a paso. Este programa, por ejemplo, lee una
lista de 5 enteros:
1
2
3

lista
for i in range 5
elemento
int input

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

lista

lista

elemento

Mejor an: si usamos append, evitaremos que cada concatenacin genere una lista nueva
copiando los valores de la antigua y aadiendo el elemento recin ledo.
1
2
3
4

lista
for i in range 5
elemento
int input
lista append elemento

Existe un mtodo alternativo que consiste en crear una lista con 5 celdas y leer despus el
valor de cada una:
1
2
3
4
5

lista
0
5
for i in range 5
lista i
int input
print lista

Evaluacin de expresiones Python en cadenas

Hemos aprendido a leer enteros, flotantes y cadenas con input, pero esa funcin no resulta til
para leer listas. Sin embargo, si evaluamos la cadena como una expresin Python, el intrprete no
tendr mayor problema. La funcin eval evala el contenido de una cadena como una expresin Python.
Estudia este ejemplo:
1
2
3
4
5
6
7
8
9

s
input
a
eval s
print a
s
input
b
eval s
print b
s
input
c
eval s
print c

Esta forma de obtener datos del tipo apropiado presenta un gran inconveniente: el usuario de
tus programas ha de saber programar en Python, ya que las expresiones deben seguir las reglas
sintcticas propias del lenguaje de programacin, y eso no es razonable. De todos modos, eval puede
resultarte de utilidad mientras desarrolles borradores de los programas que disees y manejen listas.

Supongamos que deseamos leer una lista de enteros positivos cuya longitud es desconocida.
Cmo hacerlo? Podemos ir leyendo nmeros y aadindolos a la lista hasta que nos introduzcan
un nmero negativo. El nmero negativo indicar que hemos finalizado, pero no se aadir a la
lista:
1

lista

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

2
3
4
5

nmero
int input
while nmero
0
lista append nmero
nmero
int input

221
Disea un programa que lea una lista de 10 enteros, pero asegurndose de que
todos los nmeros introducidos por el usuario son positivos. Cuando un nmero sea negativo,
lo indicaremos con un mensaje y permitiremos al usuario repetir el intento cuantas veces sea
preciso.

222
Disea un programa que lea una cadena y muestre por pantalla una lista con todas
sus palabras en minsculas. La lista devuelta no debe contener palabras repetidas.
Por ejemplo, ante la cadena
,

el programa mostrar la lista

Observa que en la lista no aparece dos veces la palabra frase, aunque s apareca dos veces
en la cadena leda.

5.2.8.

Borrado de elementos de una lista

Tambin podemos eliminar elementos de una lista. Para ello utilizamos la sentencia del
(abreviatura de delete, que en ingls significa borrar). Debes indicar qu elemento deseas
eliminar inmediatamente despus de la palabra del:
0

1 2 3

2 3

La sentencia del no produce una copia de la lista sin la celda borrada, sino que modifica
directamente la lista sobre la que opera. Fjate en qu efecto produce si dos variables apuntan
a la misma lista:

El borrado de elementos de una lista es peligroso cuando se mezcla con el recorrido de las
mismas. Vemoslo con un ejemplo. Hagamos un programa que elimina los elementos negativos
de una lista.
E
1

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Las cadenas son inmutables (y III)

Recuerda que las cadenas son inmutables. Esta propiedad tambin afecta a la posibilidad de
borrar elementos de una cadena:

2
3
4
5
6
7

for i in a
if i
0
del i
print a

Mal! Estamos usando del sobre un escalar (i), no sobre un elemento indexado de la lista
(que, en todo caso, sera a i ). Este es un error tpico de principiante. La sentencia del no se
usa as. Vamos con otra versin:
E
1
2
3
4
5
6
7

for i in range 0
if a i
0
del a i

len a

print a

Ahora s usamos correctamente la sentencia del, pero hay otro problema. Ejecutemos el
programa:
El mensaje de error nos dice que tratamos de acceder a un elemento con ndice fuera del
rango de ndices vlidos. Cmo es posible, si la lista tiene 6 elementos y el ndice i toma
valores desde 0 hasta 5? Al eliminar el tercer elemento (que es negativo), la lista ha pasado
a tener 5 elementos, es decir, el ndice de su ltimo elemento es 4. Pero el bucle decidi el
rango de ndices a recorrer antes de borrarse ese elemento, es decir, cuando la lista tena el
valor 5 como ndice del ltimo elemento. Cuando tratamos de acceder a a 5 , Python detecta
que estamos fuera del rango vlido. Es necesario que el bucle actualice el valor del ltimo
ndice vlido con cada iteracin:
E
1
2
3
4
5
6
7
8
9

i
0
while i
len a
if a i
0
del a i
i
1

print a

Ejecutemos el programa:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

No ha funcionado! El 4 no ha sido eliminado. Por qu? Inicialmente la lista era:


0

1 2 -1 -4 5 -2

Al eliminar el elemento a 2 de la lista original, i vala 2.


a

1 2 -4 5 -2

Despus del borrado, incrementamos i y eso hizo que la siguiente iteracin considerara el
posible borrado de a 3 , pero en ese instante 4 estaba en a 2 (fjate en la ltima figura),
as que nos lo saltamos. La solucin es sencilla: solo hemos de incrementar i en las iteraciones
que no producen borrado alguno:
1
2
3
4
5
6
7
8
9

10

i
0
while i
len a
if a i
0
del a i
else
i
1

print a

Ejecutemos el programa:
Ahora s!

1
2
3
4

223

Qu sale por pantalla al ejecutar este programa?:

a
list range 0
del a 1
del a 1
print a

224
Disea un programa que elimine de una lista todos los elementos de ndice par y
muestre por pantalla el resultado.
(Ejemplo: si trabaja con la lista 1 2 1 5 0 3 , esta pasar a ser 2 5 3 ).

225
Disea un programa que elimine de una lista todos los elementos de valor par y
muestre por pantalla el resultado.
2 1
5 0 3 , esta pasar a ser 1 1
5 3 ).
(Ejemplo: si trabaja con la lista 1
226
A nuestro programador novato se le ha ocurrido esta otra forma de eliminar el
elemento de ndice i de una lista a:
1

a i 1

Funciona? Si no es as, por qu? Y si funciona correctamente, qu diferencia hay con


respecto a usar del a i ?
La sentencia del tambin funciona sobre cortes:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5.2.9.

Pertenencia de un elemento a una lista

Diseemos un programa que, dados un elemento y una lista, nos diga si el elemento pertenece
o no a la lista mostrando en pantalla el mensaje
o
en funcin
del resultado.
1
2
3
4
5
6
7
8
9

10
11
12
13

E
1
2
3
4
5
6
7
8
9

10
11
12
13

elemento
5
lista
1 4

pertenece
False
for i in lista
if elemento
i
pertenece
True
break

if pertenece
print
else
print

227

Por qu este otro programa es errneo?

elemento
5
lista
1 4

for i in lista
if elemento
pertenece
else
pertenece
if pertenece
print
else
print

True

False

La pregunta de si un elemento pertenece o no a una lista es tan frecuente que Python nos
proporciona un operador predefinido que hace eso mismo. El operador es binario y se denota con
la palabra in (que en ingls significa en o pertenece a). El operador in recibe un elemento
por su parte izquierda y una lista por su parte derecha y devuelve cierto o falso. Un programa
que necesita determinar si un elemento pertenece o no a una lista y actuar en consecuencia
puede hacerlo as:
1
2
3
4
5

1
2
3
4

conjunto
1 2 3
elemento
int input
if not elemento in conjunto
conjunto append elemento
print conjunto

O, equivalentemente:

conjunto
1 2 3
elemento
int input
if elemento not in conjunto
conjunto append elemento

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

print conjunto

El operador not in es el operador in negado.

1
2
3

1
2
3

228

Qu hace este programa?

229

Qu hace este programa?

letra
input
if len letra
print letra
letra
input
if len letra
print letra

1 and

1 and

letra

or letra in

letra

or letra in

Ya te hemos dicho que Python ofrece funcionalidades similares entre tipos de datos similares.
Si el operador in funciona con listas, funcionar con cadenas, que tambin son secuencias? S.
El operador in comprueba si una cadena forma parte o no de otra4 :

Mmmm. . . podemos entonces utilizar el operador in para comprobar si una lista est contenida en otra?
No. El operador in, aplicado a listas, solo permite determinar si su operando izquierdo es un
elemento de la lista. Fjate en este otro ejemplo:
En este caso, la lista 2 7 es el segundo elemento de la lista 1
2 7
4 . Cmo?
Un elemento de una lista puede ser otra lista? S, ya te dijimos que una lista era una secuencia
de valores de cualquier tipo. Volveremos sobre este punto cuando estudiemos matrices.

5.2.10.

Ordenacin de una lista

En este apartado nos ocuparemos de un problema clsico: ordenar (de menor a mayor) los
elementos de una lista de valores. La ordenacin es muy til en infinidad de aplicaciones, as
que se ha puesto mucho empeo en estudiar algoritmos de ordenacin eficientes. De momento estudiaremos nicamente un mtodo muy sencillo (e ineficiente): el mtodo de la burbuja.
Trataremos de entender bien en qu consiste mediante un ejemplo. Supongamos que deseamos
ordenar (de menor a mayor) la lista 2 26 4 3 1 , es decir, hacer que pase a ser 1 2
3 4 26 . Se procede del siguiente modo:
Empezamos por comparar los dos primeros elementos (a 0 y a 1 ). Si estn ordenados,
los dejamos tal cual; si no, los intercambiamos. En nuestro caso ya estn ordenados.


26

4 Este comportamiento solo se da desde la versin 2.3 de Python. Versiones anteriores solo aceptaban que, si ambos
operandos eran cadenas, el operador izquierdo fuera de longitud 1.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ahora comparamos los dos siguientes (a 1 y a 2 ) y hacemos lo mismo.


0

26

En este caso no estn ordenados, as que los intercambiamos y la lista queda as:
0

26

Ahora comparamos los dos siguientes (a 2 y a 3 ) y hacemos lo mismo.


1

26

En este caso tampoco estn ordenados, as que los intercambiamos y la lista queda as:
1

26

Ahora comparamos los dos siguientes (a 3 y a 4 ), que son los ltimos.


2

26

En este caso tampoco estn ordenados, as que los intercambiamos y la lista queda as:
2

26

La lista an no est ordenada, pero fjate en qu ha ocurrido con el elemento ms grande de la


lista: ya est a la derecha del todo, que es el lugar que le corresponde definitivamente.
0

26


Desde que hemos examinado ese valor, cada paso del procedimiento lo ha movido una posicin
a la derecha. De hecho, el nombre de este procedimiento de ordenacin (mtodo de la burbuja)
toma el nombre del comportamiento que hemos observado. Es como si las burbujas en un medio
lquido subieran hacia la superficie del mismo: las ms grandes alcanzarn el nivel ms prximo
a la superficie y lo harn rpidamente.
Ahora solo es preciso ordenar los 4 primeros elementos de la lista, as que aplicamos el
mismo procedimiento a esa sublista:
Empezamos por comparar los dos primeros elementos (a 0 y a 1 ). Si estn ordenados,
los dejamos tal cual; si no, los intercambiamos.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

26


Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

La importancia de ordenar rpidamente

Ordenar el contenido de una lista es un problema importante porque se plantea en numerosos


campos de aplicacin de la programacin: la propia palabra ordenador lo pone de manifiesto.
Ordenar es, quiz, el problema ms estudiado y para el que existe mayor nmero de soluciones
diferentes, cada una con sus ventajas e inconvenientes o especialmente adaptada para tratar casos
particulares.
Podemos citar aqu a Donald E. Knuth en el tercer volumen (Sorting and searching) de The art
of computer programming, un texto clsico de programacin: Los fabricantes de ordenadores de los
aos 60 estimaron que ms del 25 por ciento del tiempo de ejecucin en sus ordenadores se dedicaba
a ordenar cuando consideraban al conjunto de sus clientes. De hecho, haba muchas instalaciones en
las que la tarea de ordenar era responsable de ms de la mitad del tiempo de computacin. De estas
estadsticas podemos concluir que (i) la ordenacin cuenta con muchas aplicaciones importantes,
(ii) mucha gente ordena cuando no debiera, o (iii) se usan comnmente algoritmos de ordenacin
ineficientes.

En nuestro caso ya estn ordenados.

Ahora comparamos los dos siguientes (a 1 y a 2 ) y hacemos lo mismo.


2

26


En este caso no estn ordenados, as que los intercambiamos y la lista queda as:
2

26


Ahora comparamos los dos siguientes (a 2 y a 3 ) y hacemos lo mismo.


2

26


En este caso tampoco estn ordenados, as que los intercambiamos y la lista queda as:
2

26


Ahora resulta que el segundo mayor elemento ya est en su posicin definitiva. Parece que cada
vez que recorremos la lista, al menos un elemento se ubica en su posicin definitiva: el mayor
de los que an estaban por ordenar.
A ver qu ocurre en el siguiente recorrido (que se limitar a la sublista de los tres primeros
elementos, pues los otros dos ya estn bien puestos):
Empezamos por comparar los dos primeros elementos (a 0 y a 1 ). Si estn ordenados,
los dejamos tal cual; si no, los intercambiamos.


En nuestro caso ya estn ordenados.


Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

4


26


Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ahora comparamos los dos siguientes (a 1 y a 2 ) y hacemos lo mismo.


0

4


26


En este caso no estn ordenados, as que los intercambiamos y la lista queda as:
0

4


26


Ya tenemos en su lugar los tres ltimos elementos.

Parece que nuestra hiptesis es cierta. An nos falta un poco para acabar:

Comparamos los dos primeros elementos (a 0 y a 1 ). Si estn ordenados, los dejamos


tal cual; si no, los intercambiamos.
0

3


4


26


No estn ordenados, as que los intercambiamos. La lista queda, finalmente, as:


0

3


4


Perfecto!: la lista ha quedado completamente ordenada.


0

1


2


3


4


26


26


Recapitulemos: para ordenar una lista de n elementos hemos de hacer n 1 pasadas. En


cada pasada conseguimos poner al menos un elemento en su posicin: el mayor. (Hacen falta
n 1 y no n porque la ltima pasada nos pone dos elementos en su sitio: el mayor va a la
segunda posicin y el menor se queda en el nico sitio que queda: la primera celda de la lista).
Intentemos codificar esa idea en Python:
1
2
3
4
5
6

lista

26

for i in range 1 len lista


hacer una pasada
print lista

Bucle que hace len(lista)-1 pasadas.

En qu consiste la i-sima pasada? En explorar todos los pares de celdas contiguas, desde
el primero hasta el ltimo. En cada paso comparamos un par de elementos:
1
2
3
4

lista

26

for i in range 1 len lista


for j in range 0 len lista

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5
6
7

1
2
3
4
5
6
7
8
9

10

comparar lista j

print lista

y lista j 1

si procede

intercambiarlos

Lo que queda debera ser fcil:

lista

26

for i in range 1 len lista


for j in range 0 len lista i
if lista j
lista j 1
elemento
lista j
lista j
lista j 1
lista j 1
elemento
print lista

Buf! Estar bien? He aqu el resultado de ejecutar el programa:

S! Pero, estar bien con seguridad? Para tener una certeza mayor, vamos a modificar el
programa para que nos diga por pantalla qu hace en cada instante:
1
2
3
4
5
6
7
8
9

10
11
12
13
14

lista

26

for i in range 1 len lista


print
i
for j in range 0 len lista i
print
if lista j
lista j 1
elemento
lista j
lista j
lista j 1
lista j 1
elemento
print
print
print lista

format j

j 1

lista

Probemos de nuevo:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Bueno, seguros de que est bien no estamos, pero al menos s parece hacer lo que toca. Ya
podemos eliminar las sentencias print que hemos introducido en el programa para hacer esta
traza automtica. Mostrar los mensajes que informan de por dnde pasa el flujo de ejecucin de
un programa y del contenido de algunas de sus variables es un truco frecuentemente utilizado
por los programadores para ver si un programa hace lo que debe y, cuando el programa tiene
errores, detectarlos y corregirlos. Por supuesto, una vez nos hemos asegurado de que el programa
funciona, hemos de eliminar las sentencias adicionales.
1

230

lista

Qu ocurrir si sustituimos la primera lnea de

por esta otra?:

Depuracin y correccin de programas

Es muy frecuente que un programa no se escriba bien a la primera. Por regla general, gran parte
del tiempo de programacin se dedica a buscar y corregir errores. Esta actividad se denomina depurar
el cdigo (en ingls, debugging, que significa desinsectar). Existen herramientas de ayuda a la
depuracin: los depuradores (en ingls, debuggers). Un depurador permite ejecutar paso a paso un
programa bajo el control del programador y consultar en cualquier instante el valor de las variables.
Pero con la ayuda de un buen depurador nunca podemos estar seguros de que un programa est
bien. Cuando un programa aborta su ejecucin o deja colgado al ordenador es evidente que hay un
error, pero, cmo podemos estar seguros de que un programa que, de momento, parece funcionar bien,
lo har siempre? Y si tiene un error tan sutil que solo se manifiesta ante una entrada muy particular?
Por extraa que sea esa entrada, cabe la posibilidad de que el programa se enfrente a ella durante su
utilizacin por parte de los usuarios. Y cuando eso ocurra, el programa abortar su ejecucin o, peor
an, ofrecer resultados mal calculados como si fueran buenos. Asusta pensar que de ese programa
puedan depender vidas humanas, cosa que ocurre en no pocos casos (programas para el clculo de
estructuras en edificaciones, para el lanzamiento y guiado de naves espaciales, para el control de
centrales nucleares, etc.).
Existe una serie de tcnicas matemticas para demostrar que un programa hace lo que se le pide.
Bajo ese enfoque, demostrar que un programa es correcto equivale a demostrar un teorema.

5.3.

De cadenas a listas y viceversa

En muchas ocasiones nos encontraremos convirtiendo cadenas en listas y viceversa. Python


nos ofrece una serie de utilidades que conviene conocer si queremos ahorrarnos muchas horas
de programacin.
Una accin frecuente consiste en obtener una lista con todas las palabras de una cadena.
He aqu cmo puedes hacerlo:
En ingls split significa partir. Funcionar con textos maliciosos, es decir, con espacios
en blanco al inicio, al final o repetidos?

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Pickle

Con lo aprendido hasta el momento ya puedes hacer algunos programas interesantes. Puedes
ir anotando en una lista ciertos datos de inters, como los apuntes de una cuenta bancaria (serie
de flotantes con valor positivo o negativo para ingresos y reintegros, respectivamente). El problema
estriba en que tu programa tendra que leer de teclado la lista entera cada vez que se ejecutara! No
es una forma natural de funcionar.
Te vamos a ensear una tcnica que te permite guardar una lista en el disco duro y recuperarla
cuando quieras. Tu programa podra empezar a ejecutarse leyendo la lista del disco duro y, justo antes
de acabar la ejecucin, guardar nuevamente la lista en el disco duro.
El mdulo pickle permite guardar/cargar estructuras de datos Python. Vemos un ejemplo:
1
2
3
4
5
6

import pickle

Creamos una lista ...


lista
1 2 3 4
y ahora la guardamos en un fichero llamado mifichero.mio.
pickle dump lista open

Al ejecutar ese programa, se crea un fichero cuyo contenido es la lista. Este otro programa leera
la misma lista:
1
2
3
4
5
6

import pickle

Leemos la lista cargndola del fichero mifichero.mio...


lista
pickle load open
y la mostramos por pantalla.
print lista

Nos hemos anticipado un poco al captulo dedicado a la gestin de ficheros, pero de este modo te
estamos capacitando para que hagas programas que pueden recordar informacin entre diferentes
ejecuciones. Si quieres saber ms, lee la documentacin del mdulo pickle. Que lo disfrutes!

S. Fantstico. Recuerdas los quebraderos de cabeza que supuso contar el nmero de palabras de una frase? Mira cmo se puede calcular con la ayuda de split:
El mtodo split acepta un argumento opcional: el carcter divisor, que por defecto es el
espacio en blanco:
231
En una cadena llamada texto disponemos de un texto formado por varias frases. Con
qu orden simple puedes contar el nmero de frases?

232
En una cadena llamada texto disponemos de un texto formado por varias frases.
Escribe un programa que determine y muestre el nmero de palabras de cada frase.

Hay un mtodo que hace lo contrario: une las cadenas de una lista en una sola cadena. Su
nombre es join (que en ingls significa unir) y se usa as:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ves? Se usa una cadena a mano izquierda del punto y se suministra una lista como argumento. El resultado es una cadena formada por los elementos de la lista separados entre s por
la cadena a mano izquierda.
233

Qu resulta de ejecutar esta sentencia?

234
Disponemos de una cadena que contiene una frase cuyas palabras estn separadas
por un nmero arbitrario de espacios en blanco. Podras estandarizar la separacin de palabras en una sola lnea Python? Por estandarizar queremos decir que la cadena no empiece ni
acabe con espacios en blanco y que cada palabra se separe de la siguiente por un nico espacio
en blanco.

Hay, adems, una funcin predefinida que permite convertir una cadena en una lista: list. La
funcin list devuelve una lista formada por los caracteres individuales de la cadena:

Los mtodos join y split son insustituibles en la caja de herramientas de un programador


Python. Acostmbrate a utilizarlos.

5.4.

Matrices

Las matrices son disposiciones bidimensionales de valores. En notacin matemtica, una


matriz se denota encerrando entre parntesis los valores, que se disponen en filas y columnas.
He aqu una matriz M:

1
2
3
2 12
6

M=
1
0 3
0 1
0

Esta matriz tiene 4 filas y 3 columnas, lo cual abreviamos diciendo que es una matriz de
dimensin 4 3.
Las listas permiten representar series de datos en una sola dimensin. Con una lista de
nmeros no se puede representar directamente una matriz, pero s con una lista de listas de
nmeros.
M

0
1
2
3

1 2 3
0

2 12 6

1 0 -3
0 -1 0

En la notacin matemtica, el elemento que ocupa la fila i-sima y la columna j-sima de


una matriz M se representa con Mi,j . Por ejemplo, el elemento de una matriz que ocupa la celda
de la fila 1 y la columna 2 se denota con M1,2 . Pero si deseamos acceder a ese elemento en la
matriz Python M, hemos de tener en cuenta que Python siempre cuenta desde cero, as que la
fila tendr ndice 0 y la columna tendr ndice 1:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Observa que utilizamos una doble indexacin para acceder a elementos de la matriz. Por
qu? El primer ndice aplicado sobre M devuelve un componente de M, que es una lista:
Y el segundo ndice accede a un elemento de esa lista, que es un entero:
235
Una matriz nula es aquella que solo contiene ceros. Construye una matriz nula de 5
filas y 5 columnas.

236
Una matriz identidad es aquella cuyos elementos en la diagonal principal, es decir,
accesibles con una expresin de la forma M i i , valen uno y el resto valen cero. Construye
una matriz identidad de 4 filas y 4 columnas.
1
2
3
4
5
6
7
8
9

10

1
2
3
4
5
6

237

Qu resulta de ejecutar este programa?

238

Qu resulta de ejecutar este programa?

M
1 0 0
0 1
print M 1 0
print M 1
1
print
for i in range 0 3
print M i
print
for i in range 0 3
for j in range 0 3
print M i j
M
1 0 0
0 1
s
0.0
for i in range 0 3
for j in range 0 3
s
M i j
print s
9

5.4.1.

Sobre la creacin de matrices

Crear una matriz consiste, pues, en crear una lista de listas. Si deseamos crear una matriz
nula (una matriz cuyos componentes sean todos igual a 0) de tamao 2 2, bastar con escribir:

Parece sencillo, pero y si nos piden una matriz nula de 6 6? Tiene 36 componentes y
escribirlos explcitamente resulta muy tedioso. Y pensemos en lo inviable de definir as una
matriz de dimensin 10 10 o 100 100!
Recuerda que hay una forma de crear listas (vectores) de cualquier tamao, siempre que
tengan el mismo valor, utilizando el operador :

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Si una matriz es una lista de listas, qu ocurrir si creamos una lista con 3 duplicados de
la lista a?
Estupendo! Ya tenemos una matriz nula de 3 6. Trabajemos con ella:

Qu ha ocurrido? No se ha modificado nicamente el componente 0 de la primera lista,


sino todos los componentes 0 de todas las listas de la matriz!
Vamos paso a paso. Primero hemos creado a:
0

0 0 0 0 0 0

A continuacin hemos definido la lista M como la copia por triplicado de la lista a:


Python nos ha obedecido copiando tres veces. . . la referencia a dicha lista!:
a

0 0 0 0 0 0

1
2

Y hemos modificado el elemento M 0


as que hemos modificado tambin M 1
a

0 asignndole el valor 1:
0 yM 2

0 , pues son el mismo elemento:


1

1 0 0 0 0 0

1
2

Por la misma razn, tampoco funcionar este modo ms directo de crear una matriz:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

0
1

0 0 0 0 0 0

Hay que construir matrices con ms cuidado, asegurndonos de que cada fila es una lista
diferente de las anteriores. Intentmoslo de nuevo:

La lista creada en la asignacin a


0
6 es diferente con cada iteracin, as que estamos
aadiendo a M una lista nueva cada vez. La memoria queda as:
M

0
1
2

0 0 0 0 0 0
0

0 0 0 0 0 0

0 0 0 0 0 0

Al ejecutarse el bucle, se ha construido una fila nueva por cada iteracin. A efectos de
construccin de la matriz, la ejecucin de aquellas sentencias equivale a la de estas:

Lo cierto es que no es necesario utilizar la variable auxiliar a:

Y con con tanta sentencia repetida, un bucle resulta ms elegante:

Observa cmo modificar ahora una celda de una fila no afecta a las dems:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1 0 0 0 0 0

0 0 0 0 0 0

239

0 0 0 0 0 0

Crea la siguiente matriz utilizando la tcnica del bucle descrita anteriormente.

1 0 0 0
0 1 0 0

0 0 1 0
0 0 0 1

240
Haz un programa que pida un entero positivo n y almacene en una variable M la
matriz identidad de n n (la que tiene unos en la diagonal principal y ceros en el resto de
celdas).

5.4.2.

Lectura de matrices

Si deseamos leer una matriz de tamao determinado, podemos crear una matriz nula como
hemos visto en el apartado anterior y, a continuacin, rellenar cada uno de sus componentes:
1
2
3
4
5
6
7
8
9

10
11
12
13

m
n

Pedimos la dimensin de la matriz,


int nput
int input

Creamos una matriz nula...


M
for i in range m
M append
0
n

... y leemos su contenido de teclado


for i in range m
for j in range n
M i j
float input

5.4.3.

format i

Qu dimensin tiene una matriz?

Cuando desebamos saber cul era la longitud de una lista utilizbamos la funcin len.
Funcionar tambin sobre matrices? Hagamos la prueba:
No funciona correctamente: solo nos devuelve el nmero de filas (que es el nmero de
componentes de la lista de listas que es la matriz). Cmo averiguar el nmero de columnas?
Fcil:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5.4.4.

Operaciones con matrices

Desarrollemos ahora algunos programas que nos ayuden a efectuar operaciones con matrices
como la suma o el producto.
Empecemos por disear un programa que sume dos matrices. Recuerda que solo es posible
sumar matrices con la misma dimensin, as que solicitaremos una sola vez el nmero de filas y
columnas:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23

m
n

Pedimos la dimensin de las matrices,


int input
int input

Creamos dos matrices nulas...


A
for i in range m
A append
0
n
B
for i in range m
B append
0

... y leemos sus contenidos de teclado.


print
for i in range m
for j in range n
A i j
float input
print
for i in range m
for j in range n
B i j
float input

format i

format i

Hemos de tener claro cmo se calcula C = A + B. Si la dimensin de A y de B es m n,


la matriz resultante ser de esa misma dimensin, y su elemento de coordenadas (i, j), es decir,
Ci,j , se calcula as:
Ci,j = Ai,j + Bi,j ,

para 1 i m y 1 j n. Recuerda que la convencin adoptada en la notacin matemtica


hace que los ndices de las matrices empiecen en 1, pero que en Python todo empieza en 0.
Codifiquemos ese clculo en Python.
1
2
3
4
5
6
7
8
9

10
11
12
13
14

m
n

int input
int input

Creamos dos matrices nulas...


A
for i in range m
A append
0
n
B
for i in range m
B append
0

... y leemos sus contenidos de teclado.


print

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

for i in range m
for j in range n
A i j
float input

print
for i in range m
for j in range n
B i j
float input

Construimos otra matriz nula para albergar el resultado.


C
for i in range m
C append
0
n
Empieza el clculo de la suma.
for i in range m
for j in range n
C i j
A i j
B i

format i

format i

Y mostramos el resultado por pantalla


print
for i in range m
for j in range n
print C i j
end
print

241
Disea un programa que lea dos matrices y calcule la diferencia entre la primera y
la segunda.

242
Disea un programa que lea una matriz y un nmero y devuelva una nueva matriz:
la que resulta de multiplicar la matriz por el nmero. (El producto de un nmero por una matriz
es la matriz que resulta de multiplicar cada elemento por dicho nmero).

Multiplicar matrices es un poco ms difcil que sumarlas (y, por descontado, el operador
no calcula el producto de matrices). Una matriz A de dimensin p q se puede multiplicar por
otra matriz B si esta es de dimensin q r, es decir, si el nmero de columnas de la primera es
igual al nmero de filas de la segunda. Hemos de pedir, pues, el nmero de filas y columnas de
la primera matriz y solo el nmero de columnas de la segunda.
1
2
3
4
5
6

p
q
r

Pedimos la dimensin de la primera matriz y el nmero de columnas de la segunda.


int input
int input
int input
Creamos dos matrices nulas...

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

1
2
3
4

A
for i in range p
A append
0

B
for i in range q
B append
0

q
r

... y leemos sus contenidos de teclado.


print
for i in range p
for j in range q
A i j
float input
print
for i in range q
for j in range r
B i j
float input

format i

format i

Sigamos. La matriz resultante del producto es de dimensin p r:

Creamos una matriz nula ms para el resultado...


C
for i in range p
C append
0
r

El elemento de coordenadas Ci,j se calcula as:

para 1 i p y 1 j r.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

p
q
r

Ci,j =

q

k=1

Ai,k Bk,j ,

Pedimos la dimensin de la primera matriz y el nmero de columnas de la segunda.


int input
int input
int input

Creamos dos matrices nulas...


A
for i in range p
A append
0
q
B
for i in range q
B append
0

... y leemos sus contenidos de teclado.


print
for i in range p
for j in range q
A i j
float input
print
for i in range q
for j in range r
B i j
float input

Creamos una matriz nula ms para el resultado...

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

format i

format i

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

27
28
29
30
31
32
33
34
35

C
for i in range p
C append
0

Y efectuamos el clculo del producto.


for i in range p
for j in range r
for k in range q
C i j
A i k
B k

Complicado? No tanto: a fin de cuentas las lneas 3435 corresponden al clculo de un


sumatorio, algo que hemos codificado en Python una y otra vez.
Solo falta mostrar el resultado por pantalla, pero ya hemos visto cmo se hace. Completa t
el programa.
Otros usos de las matrices

De momento solo hemos discutido aplicaciones numricas de las matrices, pero son tiles en
muchos otros campos. Por ejemplo, muchos juegos de ordenador representan informaciones mediante
matrices:

El tablero de tres en raya es una matriz de 3 3 en el que cada casilla est vaca o contiene
la ficha de un jugador, as que podramos codificar con el valor 0 el que est vaca, con el valor
1 el que tenga una ficha de un jugador y con un 2 el que tenga una ficha del otro jugador.
Un tablero de ajedrez es una matriz de 8 8 en el que cada casilla est vaca o contiene una
pieza. Cmo las codificaras?

El tablero del juego del buscaminas es una matriz. En cada celda se codifica si hay bomba o
no y si el usuario la ha descubierto ya o no.
...

Las cmaras de video digitales permiten recoger imgenes, cada una de las cuales no es ms que
una matriz de valores. Si la imagen es en blanco y negro, cada valor es un nmero que representa
la intensidad de brillo en ese punto; si la imagen es en color, cada casilla contiene tres valores: la
intensidad de la componente roja, la de la componente verde y la de la componente azul. Los sistemas
de visin artificial aplican transformaciones a esas matrices y las analizan para tratar de identificar
en ellas determinados objetos.

243
La traspuesta de una matriz A de dimensin m n es una matriz AT de dimensin
n m tal que ATi,j = Aj,i . Por ejemplo, si

entonces:

1
2
A=
1
10

1
AT = 2
3

2
12
0
1

2
12
6

3
6

3
0

1
0
3

10
1
0

Disea un programa que lea una matriz y muestre su traspuesta.

244
Disea un programa tal que lea una matriz A de dimensin m n y muestre un
vector v de talla n tal que
m

Ai,j ,
vj =

para j entre 1 y n.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

i=1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

245
Disea un programa que lea una matriz A de dimensin m n y muestre un vector v
de talla min(n, m) tal que
i
i 

vi =
Aj,k ,
para i entre 1 y min(n, m).

j=1 k=1

246
Disea un programa que, dada una matriz, determine si la suma de los elementos de
cualquiera de sus filas es igual a la suma de los elementos de cualquiera de sus columnas.

247
Una matriz cuadrada es triangular superior si todos los elementos por debajo de la
diagonal principal son nulos. Por ejemplo, esta matriz es triangular superior:

1 2
3
6
A = 0 12
0 0 3
Disea un programa que diga si una matriz es o no es triangular superior.

5.4.5.

El juego de la vida

El juego de la vida es un juego sin jugadores. Se trata de colocar una serie de fichas en un
tablero y dejar que evolucionen siguiendo unas reglas extremadamente simples. Lo curioso es
que esas reglas dan origen a una gran complejidad que hace apasionante la mera observacin
de la evolucin de las fichas en el tablero (hay gustos para todo).
En el juego original se utiliza un tablero (una matriz) con infinitas filas y columnas. Como
disponer de una matriz de dimensin infinita en un programa es imposible, supondremos que
presenta dimensin m n, donde m y n son valores escogidos por nosotros. Cada celda del
tablero contiene una clula que puede estar viva o muerta. Representaremos las clulas vivas
con su casilla de color negro y las clulas muertas con la celda en blanco. Cada casilla del
tablero cuenta con ocho celdas vecinas. El mundo del juego de la vida est gobernado por un
reloj que marca una serie de pulsos con los que mueren y nacen clulas. Cundo nace y cundo
muere una clula solo depende de cuntas clulas vecinas estn vivas. He aqu las reglas:
1) Regla del nacimiento. Una clula muerta resucita si tiene exactamente tres vecinos vivos. En
estas figuras te sealamos celdas muertas que pasan a estar vivas con el siguiente pulso:

2) Regla de la supervivencia. Una celda viva permanece viva si tiene dos o tres vecinos. Aqu te
sealamos clulas que ahora estn vivas y permanecern as tras el siguiente pulso:

3) Regla de la superpoblacin. Una clula muere o permanece muerta si tiene cuatro o ms


vecinos. Estas figuras muestran clulas que ahora estn vivas o muertas y estarn muertas
tras el siguiente pulso:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4) Regla del aislamiento. Una clula muere o permanece muerta si tiene menos de dos vecinos.
En estas figuras te sealamos clulas que ahora estn vivas o muertas y estarn muertas tras
el siguiente pulso:

Vamos a hacer un programa que muestre la evolucin del juego de la vida durante una serie
de pulsos de reloj. Empezaremos con un prototipo que nos muestra la evolucin del tablero en
el terminal.
Necesitamos representar de algn modo nuestro universo: el tablero de celdas. Evidentemente, se trata de una matriz. De qu dimensin? La que queramos. Usaremos dos variables:
filas y columnas para la dimensin y una matriz de valores lgicos para representar el tablero.
Inicializaremos el tablero con valores False y, para hacer pruebas, supondremos que la matriz
es de 10 10:
1
2
3
4
5
6

filas
10
columnas

10

tablero
for i in range filas
tablero append

False

columnas

Ahora deberamos inicializar el universo ubicando algunas clulas vivas. De lo contrario,


nunca aparecer vida en el juego. Un patrn sencillo y a la vez interesante es este:

Fjate en qu ocurre tras unos pocos pulsos de actividad:

1
2
3

Es lo que denominamos un oscilador: alterna entre dos o ms configuraciones.

tablero 4
tablero 5
tablero 6

5
5
5

True
True
True

Ahora deberamos representar el tablero de juego en pantalla. Usaremos de momento el


terminal de texto: un punto representar una clula muerta y un asterisco representar una
clula viva.
1
2
3
4
5
6
7
8

filas
10
columnas

10

tablero
for i in range filas
tablero append
tablero 4

False

True

columnas

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

10
11
12
13
14
15
16
17
18

tablero 5
tablero 6

5
5

True
True

for y in range filas


for x in range columnas
if tablero y x
print
end
else
print
end
print

Aqu tienes lo que muestra por pantalla, de momento, el programa:

Sigamos. El mundo del juego est gobernado por un reloj. Nosotros seguiremos la evolucin
del juego durante un nmero determinado de pulsos. Fijemos, de momento, el nmero de pulsos
a 6:
1
2
3

1
2
3
4
5
6
7
8
9

10
11
12

1
2
3
4
5
6
7
8
9

10
11

pulsos
6
for t in range pulsos
Acciones asociadas a cada pulso de reloj

Qu acciones asociamos a cada pulso? Primero, actualizar el tablero, y segundo, mostrarlo:

for t in range pulsos


Actualizar el tablero

Representar el tablero.
print
t 1
for y in range filas
for x in range columnas
if tablero y x
print
end
else
print
end
print

Vamos a actualizar el tablero. Detallemos un poco ms esa tarea:

for t in range pulsos


Actualizar el tablero.
for y in range filas
for x in range columnas
Calcular el nmero de vecinos de la celda que estamos visitando.
n
calcular el nmero de vecinos
Aplicar las reglas.
if tablero y x and n
2 or n
3
Supervivencia
tablero y x
True
elif not tablero y x and n
3
Nacimiento
tablero y x
True

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

else

12
13
14
15
16

Superpoblacin y aislamiento
tablero y x
False

Representar el tablero.

Solo nos falta determinar el nmero de vecinos. Cmo lo hacemos? Fcil: consultando cada
una de las casillas vecinas e incrementando un contador (inicializado a cero) cada vez que
encontremos una clula viva:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

filas
10
columnas

10

tablero
for i in range filas
tablero append
tablero 4
tablero 5
tablero 6

5
5
5

False

True
True
True

columnas

Representar el tablero.
print
for y in range filas
for x in range columnas
if tablero y x
print
end
else
print
end
print

pulsos
6
for t in range pulsos
Actualizar el tablero.
for y in range filas
for x in range columnas
Calcular el nmero de vecinos de la celda que estamos visitando.
n
0
if tablero y 1 x 1
n
1
if tablero y
x 1
n
1
if tablero y 1 x 1
n
1
if tablero y 1
x
n
1
if tablero y 1
x
n
1
if tablero y 1 x 1
n
1
if tablero y
x 1
n
1
if tablero y 1 x 1
n
1
Aplicar las reglas.
if tablero y x and n
2 or n
3
Supervivencia
tablero y x
True
elif not tablero y x and n
3
Nacimiento
tablero y x
True
else
Superpoblacin y aislamiento

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

51
52
53
54
55
56
57
58
59
60

tablero y x
False
Representar el tablero.
print
t 1
for y in range filas
for x in range columnas
if tablero y x
print
end
else
print
end
print

Ya est. Ejecutemos el programa:

Qu ha ido mal? Python nos dice que nos hemos salido de rango al acceder a un elemento
de la matriz. Ya est claro: cuando x vale columnas 1, x 1 vale columnas y nos salimos del
rango vlido de ndices. (Hay un problema similar cuando x vale 0 y tratamos de consultar la
columna x 1, solo que no se produce un error de ejecucin porque la columna de ndice 1
existe: es la columna columnas 1!). El juego de la vida original asume que el tablero es infinito.
Nosotros hemos de jugar con un tablero que tiene lmites, as que tendremos que tratar de modo
especial las casillas fronterizas, pues no tienen 8 casillas colindantes. Esta nueva versin tiene
esa precaucin:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

filas
10
columnas

10

tablero
for i in range filas
tablero append
tablero 4
tablero 5
tablero 6

5
5
5

False

True
True
True

columnas

Representar el tablero.
print
for y in range filas
for x in range columnas
if tablero y x
print
end
else
print
end
print
pulsos
6
for t in range pulsos
Actualizar el tablero.
for y in range filas

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

for x in range columnas


Calcular el nmero de vecinos de la celda que estamos visitando.
n
0
if y
0 and x
0 and tablero y 1 x 1
n
1
if x
0 and tablero y
x 1
n
1
if y
filas 1 and x
0 and tablero y 1 x 1
n
1
if y
0 and tablero y 1
x
n
1
if y
filas 1 and tablero y 1
x
n
1
if y
0 and x
columnas 1 and tablero y 1 x 1
n
1
if x
columnas 1 and tablero y
x 1
n
1
if y
filas 1 and x
columnas 1 and tablero y 1 x 1
n
1
Aplicar las reglas.
if tablero y x and n
2 or n
3
Supervivencia
tablero y x
True
elif not tablero y x and n
3
Nacimiento
tablero y x
True
else
Superpoblacin y aislamiento
tablero y x
False
Representar el tablero.
print
t 1
for y in range filas
for x in range columnas
if tablero y x
print
end
else
print
end
print

Ejecutemos ahora el programa:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Alto! Qu ha pasado? No aparece el patrn de oscilacin que esperbamos! Haz una traza
para ver si averiguas qu ha pasado. Date un poco de tiempo antes de seguir leyendo.
De acuerdo. Confiamos en que has reflexionado un poco y ya has encontrado una explicacin
de lo ocurrido antes de leer esto. Confirma que ests en lo cierto: ha ocurrido que estamos
aplicando las reglas sobre un tablero que se modifica durante la propia aplicacin de las reglas,
y eso no es vlido. Numeremos algunas celdas afectadas por el oscilador para explicar lo ocurrido:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Cuando hemos procesado la celda 1, su nmero de vecinos era 0 as que ha muerto (regla de
aislamiento). La celda 2 pasa entonces a tener 2 vecinos, as que muere. Si la celda 1 no hubiera
muerto an, hubisemos contado 3 vecinos, y la celda 2 hubiese pasado a estar viva (regla de
nacimiento). La celda 3 tiene ahora 1 vecino, luego muere (lo correcto hubiera sido contar 2
vecinos y aplicar la regla de supervivencia). La celda 4 cuenta con un solo vecino (deberan
haber sido 3), luego muere. Y la celda 5 no tiene vecinos, luego tambin muere. Resultado: todas
las clulas mueren.
Cmo podemos ingeniar un mtodo que no mate/resucite clulas durante el propio pulso?
Una tcnica sencilla consiste en usar dos tableros. Uno de ellos no se modifica durante la
aplicacin de las reglas y los vecinos se cuentan sobre su configuracin. La nueva configuracin
se va calculando y escribiendo en el segundo tablero. Cuando finaliza el proceso, el tablero
actual copia su contenido del tablero nuevo. Te ofrecemos ya una versin completa del juego:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

filas
10
columnas

10

tablero
for i in range filas
tablero append
tablero 4
tablero 5
tablero 6

5
5
5

False

True
True
True

columnas

Representar el tablero.
print
for y in range filas
for x in range columnas
if tablero y x
print
end
else
print
end
print

pulsos
6
for t in range pulsos
Preparar un nuevo tablero.
nuevo
for i in range filas
nuevo append False columnas

Actualizar el tablero.
for y in range filas
for x in range columnas
Calcular el nmero de vecinos de la celda que estamos visitando.
n
0
if y
0 and x
0 and tablero y 1 x 1
n
1
if x
0 and tablero y
x 1
n
1
if y
filas 1 and x
0 and tablero y 1 x 1
n
1
if y
0 and tablero y 1
x
n
1
if y
filas 1 and tablero y 1
x
n
1
if y
0 and x
columnas 1 and tablero y 1 x 1
n
1
if x
columnas 1 and tablero y
x 1
n
1

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

if y

filas 1 and x
columnas 1 and tablero y 1 x 1
n
1
Aplicar las reglas.
if tablero y x and n
2 or n
3
Supervivencia
nuevo y x
True
elif not tablero y x and n
3
Nacimiento
nuevo y x
True
else
Superpoblacin y aislamiento
nuevo y x
False

Actualizar el tablero.
tablero
nuevo

Representar el tablero.
print
t 1
for y in range filas
for x in range columnas
if tablero y x
print
end
else
print
end
print

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ahora s. Puedes probar algunas configuraciones del juego de la vida tan interesantes que
tienen nombre propio (conviene que los pruebes en tableros de gran dimensin):
La rana:

El deslizador:

La abeja reina lanzadora:

1
2

248

Funciona esta otra forma de contar los vecinos de la casilla de la fila y y columna x?

if tablero y
n
1

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

El juego del universo?

El juego de la vida fue inventado en 1970 por el matemtico John H. Conway y popularizado por
Martin Gardner en su columna de Scientific American. El juego de la vida es un caso particular de
autmata celular, un sistema en el que ciertas reglas deciden acerca del valor que debe tomar una
celda en un tablero a partir de los valores de sus vecinas.
Los autmatas celulares ilustran la denominada complejidad emergente, un campo relativamente
reciente dedicado a estudiar la aparicin de patrones complejos y la autoorganizacin a partir de
reglas simples. Parecen proporcionar un buen modelo para numerosos fenmenos naturales, como la
pigmentacin en conchas y otros animales.
Una hiptesis interesante es que la naturaleza no es ms que un superordenador que est jugando
alguna variante del juego de la vida. Una idea extravagante? Stephen Wolfram, el autor principal
del celebrado programa Mathematica, se ha encerrado una dcada para investigar esta cuestin. El
resultado: un polmico libro titulado A new kind of science en el que propone un nuevo tipo de
ciencia para estudiar el funcionamiento del universo a partir del anlisis y observacin de autmatas
celulares.
Internet est plagada de pginas web dedicadas al juego de la vida y a los autmatas celulares.
Bscalas y divirtete con la infinidad de curiosos patrones que generan las formas ms increbles.
3
4
5
6
7
8
9

else

n
0
for i in
1 0 1
for j in
1 0 1
if y i
0 and y i
filas and x j
if tablero y i x j
n
1

0 and x j

columnas

249
El juego de la vida parametrizado es una generalizacin del juego de la vida. En
l, el nmero de vecinos vivos necesarios para activar las reglas de nacimiento, supervivencia,
aislamiento y superpoblacin estn parametrizados. Haz un programa que solicite al usuario el
nmero de clulas vecinas vivas necesarias para que se disparen las diferentes reglas y muestre
cmo evoluciona el tablero con ellas.

250
El juego de la vida toroidal se juega sobre un tablero de dimensin finita m n con
unas reglas de vecindad diferentes. Una casilla de coordenadas (y, x) tiene siempre 8 vecinas,
aunque est en un borde:
((y 1) mod m, (x 1) mod n)
(y, (x 1) mod n)
((y + 1) mod m, (x 1) mod n)

((y 1) mod m, x)
((y + 1) mod m, x)

((y 1) mod m, (x + 1) mod n)


(y, (x + 1) mod n)
((y + 1) mod m, (x + 1) mod n)

donde mod es el operador mdulo (en Python, ).


Implementa el juego de la vida toroidal con los grficos de tortuga.

251
El juego de la vida es un tipo particular de autmata celular bidimensional. Hay
autmatas celulares unidimensionales. En ellos, una lista de valores (en su versin ms simple,
ceros y unos) evoluciona a lo largo del tiempo a partir del estado de sus celdas vecinas (solo las
celdas izquierda y derecha en su versin ms simple) y de ella misma en el instante anterior.
Por ejemplo, una regla 001 1 se lee como la clula est viva si en la iteracin anterior
estaba muerta y tena una clula muerta a la izquierda y una clula viva a la derecha. Una
especificacin completa tiene este aspecto:
000 0, 001 1, 010 1, 011 0, 100 1, 101 1, 110 0, 111 0,

Y aqu tienes una representacin (usando asteriscos para los unos y puntos para los ceros) de la
evolucin del sistema durante sus primeros pulsos partiendo de una configuracin muy sencilla
(un solo uno):
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Implementa un programa para estudiar la evolucin de autmatas celulares unidimensionales.


El programa leer un conjunto de reglas por teclado y un nmero de pulsos. A continuacin,
mostrar en el terminal de texto la evolucin del autmata partiendo de una configuracin con
solo una celda viva que ocupa la posicin central del universo.
Cuando tengas el programa, explora las siguientes reglas:
000 0, 001 1, 010 1, 011 1, 100 1, 101 0, 110 0, 111 0.
000 0, 001 0, 010 1, 011 1, 100 1, 101 0, 110 0, 111 0.
000 0, 001 1, 010 1, 011 1, 100 0, 101 1, 110 1, 111 0.
000 0, 001 1, 010 1, 011 1, 100 0, 101 1, 110 1, 111 0.
000 0, 001 1, 010 1, 011 0, 100 1, 101 1, 110 0, 111 1.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Captulo 6

Funciones

Y ellos, naturalmente, responden a sus nombres, no? observ al desgaire


el Mosquito.
Nunca o decir tal cosa.
Pues de qu les sirve tenerlos pregunt el Mosquito si no responden a
sus nombres?
Alicia en el pas de las maravillas, Lewis Carroll

En captulos anteriores hemos aprendido a utilizar funciones. Algunas de ellas estn predefinidas (abs, round, etc.) mientras que otras deben importarse de mdulos antes de poder ser
usadas (por ejemplo, sin y cos se importan del mdulo math). En este tema aprenderemos a definir nuestras propias funciones. Definiendo nuevas funciones estaremos enseando a Python
a hacer clculos que inicialmente no sabe hacer y, en cierto modo, adaptando el lenguaje de
programacin al tipo de problemas que deseamos resolver, enriquecindolo para que el programador pueda ejecutar acciones complejas de un modo sencillo: llamando a funciones desde su
programa.
Ya has usado mdulos, es decir, ficheros que contienen funciones y variables de valor predefinido que puedes importar en tus programas. En este captulo aprenderemos a crear nuestros
propios mdulos, de manera que reutilizar nuestras funciones en varios programas resultar
extremadamente sencillo: bastar con importarlas.

6.1.

Uso de funciones

Denominaremos activar, invocar o llamar a una funcin a la accin de usarla. Las funciones
que hemos aprendido a invocar reciben cero, uno o ms argumentos separados por comas y
encerrados entre un par de parntesis y pueden devolver un valor o no devolver nada.

Podemos llamar a una funcin desde una expresin. Como el resultado tiene un tipo determinado, hemos de estar atentos a que este sea compatible con la operacin y tipo de los operandos
con los que se combina:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ves? En el ltimo caso se ha producido un error de tipos porque se ha intentado sumar una
cadena, que es el tipo de dato del valor devuelto por str, a un entero.
Observa que los argumentos de una funcin tambin pueden ser expresiones:

6.2.

Definicin de funciones

6.2.1.

Definicin y uso de funciones con un solo parmetro

Vamos a estudiar el modo en que podemos definir (y usar) nuestras propias funciones Python. Estudiaremos en primer lugar cmo definir y llamar a funciones que devuelven un valor
y pasaremos despus a presentar los denominados procedimientos: funciones que no devuelven
ningn valor. Adems de los conceptos y tcnicas que te iremos presentando, es interesante que
te fijes en cmo desarrollamos los diferentes programas de ejemplo.
Empezaremos definiendo una funcin muy sencilla, una que recibe un nmero y devuelve
el cuadrado de dicho nmero. El nombre que daremos a la funcin es cuadrado. Observa este
fragmento de programa:
1
2

def cuadrado x
return x
2

Ya est. Acabamos de definir la funcin cuadrado que se aplica sobre un valor al que llamamos x y devuelve un nmero: el resultado de elevar x al cuadrado. En el programa aparecen dos
nuevas palabras reservadas: def y return. La palabra def es abreviatura de define y return
significa devuelve en ingls. Podramos leer el programa anterior como define cuadrado de x
como el valor que resulta de elevar x al cuadrado.
En las lneas que siguen a su definicin, la funcin cuadrado puede utilizarse del mismo
modo que las funciones predefinidas:
1
2
3
4
5
6

def cuadrado x
return x
2

print cuadrado 2
a
1
cuadrado 3
print cuadrado a
3

Este es el resultado de ejecutar el programa:

En cada caso, el resultado de la expresin que sigue entre parntesis al nombre de la funcin
es utilizado como valor de x durante la ejecucin de cuadrado. En la primera llamada (lnea 4)
el valor es 2, en la siguiente llamada es 3 y en la ltima, 30. Fcil, no?
Detengmonos un momento para aprender algunos trminos nuevos. La lnea que empieza con
def es la cabecera de la funcin y el fragmento de programa que contiene los clculos que debe
efectuar la funcin se denomina cuerpo de la funcin. Cuando estamos definiendo una funcin, su
parmetro se denomina parmetro formal (aunque, por abreviar, normalmente usaremos el trmino
parmetro, sin ms). El valor que pasamos a una funcin cuando la invocamos se denomina
parmetro real o argumento. Las porciones de un programa que no son cuerpo de funciones
forman parte del programa principal: son las sentencias que se ejecutarn cuando el programa
entre en accin. El cuerpo de las funciones solo se ejecutar si se producen las correspondientes
llamadas.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Parmetro formal (o simplemente parmetro)

def cuadrado x
return x

Cabecera
Cuerpo

Valor de retorno

print cuadrado 2

Llamada, invocacin o activacin


Argumento

Definir no es invocar

1
2

Si intentamos ejecutar este programa:

def cuadrado x
return x
2

no ocurrir nada en absoluto; bueno, al menos nada que aparezca por pantalla. La definicin de
una funcin solo hace que Python aprenda silenciosamente un mtodo de clculo asociado al
identificador cuadrado. Nada ms. Hagamos la prueba ejecutando el programa:

Lo ves? No se ha impreso nada en pantalla. No se trata de que no haya ningn print, sino de
que definir una funcin es un proceso que no tiene eco en pantalla. Repetimos: definir una funcin
solo asocia un mtodo de clculo a un identificador y no supone ejecutar dicho mtodo de clculo.
Este otro programa s muestra algo por pantalla:
1
2
3
4

def cuadrado x
return x
2
print cuadrado 2

Al invocar a la funcin cuadrado (lnea 4) se ejecuta esta. En el programa, la invocacin de la


ltima lnea provoca la ejecucin de la lnea 2 con un valor de x igual a 2 (argumento de la llamada).
El valor devuelto con return es mostrado en pantalla como efecto de la sentencia print de la lnea 4.
Hagamos la prueba:

Las reglas para dar nombre a las funciones y a sus parmetros son las mismas que seguimos
para dar nombre a las variables: solo se pueden usar letras, dgitos y el carcter de subrayado;
la primera letra del nombre no puede ser un nmero; y no se pueden usar palabras reservadas.
Pero, cuidado!: no debes dar el mismo nombre a una funcin y a una variable. En Python, cada
nombre debe identificar claramente un nico elemento: una variable o una funcin1 .

Al definir una funcin cuadrado es como si hubisemos creado una mquina de calcular
cuadrados. Desde la ptica de su uso, podemos representar la funcin como una caja que
transforma un dato de entrada en un dato de salida:
1 Ms

adelante, al presentar las variables locales, matizaremos esta afirmacin.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Definicin de funciones desde el entorno interactivo

Hemos aprendido a definir funciones dentro de un programa. Tambin puedes definir funciones
desde el entorno interactivo de Python. Te vamos a ensear paso a paso qu ocurre en el entorno
interactivo cuando estamos definiendo una funcin.
En primer lugar aparece el prompt. Podemos escribir entonces la primera lnea:
Python nos responde con tres puntos (
). Esos tres puntos son el llamado prompt secundario:
indica que la accin de definir la funcin no se ha completado an y nos pide ms sentencias.
Escribimos a continuacin la segunda lnea respetando el sangrado que le corresponde:
Nuevamente Python responde con el prompt secundario. Es necesario que le demos una vez ms
al retorno de carro para que Python entienda que ya hemos acabado de definir la funcin:

Ahora aparece de nuevo el prompt principal o primario. Python ha aprendido la funcin y est
listo para que introduzcamos nuevas sentencias o expresiones.

cuadrado

x2

Cuando invocas a la funcin, le ests conectando un valor a la entrada, as que la mquina


de calcular cuadrados se pone en marcha y produce la solucin deseada:

cuadrado

Ojo: no hay una nica forma de construir la mquina de calcular cuadrados. Fjate en esta
definicin alternativa:
1
2

def cuadrado x
return x
x

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Se trata de una definicin tan vlida como la anterior, ni mejor, ni peor. Como usuarios de la
funcin, poco nos importa cmo hace el clculo2 ; lo que importa es qu datos recibe y qu valor
devuelve.
Vamos con un ejemplo ms: una funcin que calcula el valor de x por el seno de x:
1
2
3
4

from math import sin


def xsin x
return x

sin x

Lo interesante de este ejemplo es que la funcin definida, xsin, contiene una llamada a otra
funcin (sin). No hay problema: desde una funcin puedes invocar a cualquier otra.
1
2

Una confusin frecuente

Supongamos que definimos una funcin con un parmetro x como esta:

def cubo x
return x

Es frecuente en los aprendices confundir el parmetro x con una variable x. As, les parece extrao
que podamos invocar a la funcin de este modo:
1
2

y
1
print cubo y

Cmo es que ahora llamamos y a lo que se llamaba x? No hay problema alguno. Al definir una
funcin, usamos un identificador cualquiera para referirnos al parmetro. Tanto da que se llame x
como y. Esta otra definicin de cubo es absolutamente equivalente:
1
2

def cubo z
return z

La definicin se puede leer as: si te pasan un valor, digamos z, devuelve ese valor elevado al
cubo. Usamos el nombre z (o x) solo para poder referirnos a l en el cuerpo de la funcin.

252
Define una funcin llamada raz_cbica que devuelva el valor de 3 x.

(Nota: recuerda que la notacin 3 x no es ms que una forma de expresar x 1/3 ).

253
Define una funcin llamada rea_crculo que, a partir del radio de un crculo, devuelva
el valor de su rea. Utiliza el valor 3.1416 como aproximacin de o importa el valor de que
encontrars en el mdulo math.
(Recuerda que el rea de un crculo de radio r es r 2 ).
254
Define una funcin que convierta grados Farenheit en grados centgrados.
(Para calcular los grados centgrados has de restar 32 a los grados Farenheit y multiplicar
el resultado por cinco novenos).
255

Define una funcin que convierta grados centgrados en grados Farenheit.

257

Define una funcin que convierta grados en radianes.

256
Define una funcin que convierta radianes en grados.
(Recuerda que 360 grados son 2 radianes).

2 . . . por el momento. Hay muchas formas de hacer el clculo, pero unas resultan ms eficientes (ms rpidas) que
otras. Naturalmente, cuando podamos elegir, escogeremos la forma ms eficiente.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

En el cuerpo de una funcin no solo pueden aparecer sentencias return; tambin podemos usar
estructuras de control: sentencias condicionales, bucles, etc. Lo podemos comprobar diseando
una funcin que recibe un nmero y devuelve un booleano. El valor de entrada es la edad de una
persona y la funcin devuelve True si la persona es mayor de edad y False en caso contrario:
es_mayor_de_edad
edad

True o False

Cuando llamas a la funcin, esta se activa para producir un resultado concreto (en nuestro
caso, o bien devuelve True o bien devuelve False):
1

es_mayor_de_edad 23

23
1

es_mayor_de_edad 12

12

es_mayor_de_edad
edad

es_mayor_de_edad
edad

True

False

Una forma usual de devolver valores de funcin es a travs de un solo return ubicado al final
del cuerpo de la funcin:
1
2
3
4
5
6

def es_mayor_de_edad edad


if edad
18
resultado
False
else
resultado
True
return resultado

Pero no es el nico modo en que puedes devolver diferentes valores. Mira esta otra definicin
de la misma funcin:
1
2
3
4
5

def es_mayor_de_edad edad


if edad
18
return False
else
return True

Aparecen dos sentencias return: cuando la ejecucin llega a cualquiera de ellas, finaliza
inmediatamente la llamada a la funcin y se devuelve el valor que sigue al return. Podemos
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

asimilar el comportamiento de return al de break: una sentencia break fuerza a terminar la


ejecucin de un bucle y una sentencia return fuerza a terminar la ejecucin de una llamada a
funcin.
1
2
3
4

1
2

258

Es este programa equivalente al que acabamos de ver?

259

Es este programa equivalente al que acabamos de ver?

def es_mayor_de_edad edad


if edad
18
return False
return True

def es_mayor_de_edad edad


return edad
18

260
La ltima letra del DNI puede calcularse a partir del nmero. Para ello solo tienes
que dividir el nmero por 23 y quedarte con el resto, que es un nmero entre 0 y 22. La letra
que corresponde a cada nmero la tienes en esta tabla:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

Define una funcin llamada letra_dni que, dado un nmero de DNI, devuelva la letra que le
corresponde.

261
Disea una funcin que reciba una cadena y devuelva cierto si empieza por minscula
y falso en caso contrario.

262
Disea una funcin llamada es_repeticin que reciba una cadena y nos diga si la
cadena est formada mediante la concatenacin de una cadena consigo misma. Por ejemplo,
es_repeticin
devolver True, pues la cadena
est formada con la cadena
repetida; por contra es_repeticin
devolver False.

Y ahora, un problema ms complicado. Vamos a disear una funcin que nos diga si un
nmero dado es o no es perfecto. Se dice que un nmero es perfecto si es igual a la suma de
todos sus divisores excludo l mismo. Por ejemplo, 28 es un nmero perfecto, pues sus divisores
(excepto l mismo) son 1, 2, 4, 7 y 14, que suman 28.
Empecemos. La funcin, a la que llamaremos es_perfecto, recibir un solo dato (el nmero
sobre el que hacemos la pregunta) y devolver un valor booleano:
n

1
2

es_perfecto

True o False

La cabecera de la funcin est clara:

def es_perfecto n

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Y por dnde seguimos? Vamos por partes. En primer lugar estamos interesados en conocer
todos los divisores del nmero. Una vez tengamos claro cmo saber cules son, los sumaremos.
Si la suma coincide con el nmero original, este es perfecto; si no, no. Podemos usar un bucle
y preguntar a todos los nmeros entre 1 y n 1 si son divisores de n:
1
2
3
4

def es_perfecto n
for i in range 1 n
if i es divisor de n

Observa cmo seguimos siempre las reglas de sangrado de cdigo que impone Python. Y
cmo preguntamos ahora si un nmero es divisor de otro? El operador mdulo devuelve el
resto de la divisin y resuelve fcilmente la cuestin:
1
2
3
4

def es_perfecto n
for i in range 1 n
if n
i
0

La lnea 4 solo se ejecutar para valores de i que son divisores de n. Qu hemos de hacer a
continuacin? Deseamos sumar todos los divisores y ya conocemos la plantilla para calcular
sumatorios:
1
2
3
4
5
6

def es_perfecto n
sumatorio
0
for i in range 1 n
if n
i
0
sumatorio

Qu queda por hacer? Comprobar si el nmero es perfecto y devolver True o False, segn
proceda:
1
2
3
4
5
6
7
8
9

def es_perfecto n
sumatorio
0
for i in range 1 n
if n
i
0
sumatorio
if sumatorio
n
return True
else
return False

Y ya est. Bueno, podemos simplificar un poco las cuatro ltimas lneas y convertirlas en
una sola. Observa esta nueva versin:
1
2
3
4
5
6

def es_perfecto n
sumatorio
0
for i in range 1 n
if n
i
0
sumatorio
i
return sumatorio
n

Qu hace la ltima lnea? Devuelve el resultado de evaluar la expresin lgica que compara
sumatorio con n: si ambos nmeros son iguales, devuelve True, y si no, devuelve False. Mejor,
no?
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4
5
6

263

En qu se ha equivocado nuestro aprendiz de programador al escribir esta funcin?

def es_perfecto n
for i in range 1 n
sumatorio
0
if n
i
0
sumatorio
i
return sumatorio
n

264
Mejora la funcin es_perfecto hacindola ms rpida. Es realmente necesario considerar todos los nmeros entre 1 y n 1?

265
Disea una funcin que devuelva una lista con los nmeros perfectos comprendidos
entre 1 y n, siendo n un entero que nos proporciona el usuario.

266
Define una funcin que devuelva el nmero de das que tiene un ao determinado.
Ten en cuenta que un ao es bisiesto si es divisible por 4 y no divisible por 100, excepto si es
tambin divisible por 400, en cuyo caso es bisiesto.
(Ejemplos: El nmero de das de 2002 es 365: el nmero 2002 no es divisible por 4, as que
no es bisiesto. El ao 2004 es bisiesto y tiene 366 das: el nmero 2004 es divisible por 4, pero
no por 100, as que es bisiesto. El ao 1900 es divisible por 4, pero no es bisiesto porque es
divisible por 100 y no por 400. El ao 2000 s es bisiesto: el nmero 2000 es divisible por 4 y,
aunque es divisible por 100, tambin lo es por 400).

Hasta el momento nos hemos limitado a suministrar valores escalares como argumentos de
una funcin, pero tambin es posible suministrar argumentos de tipo secuencial. Vemoslo con
un ejemplo: una funcin que recibe una lista de nmeros y nos devuelve el sumatorio de todos
sus elementos.
lista

1
2
3
4
5

1
2
3
4
5
6
7
8

sumatorio

suma de todos los elementos de la lista

def sumatorio lista


suma
0
for nmero in lista
suma
nmero
return suma

Podemos usar la funcin as:

def sumatorio lista


suma
0
for nmero in lista
suma
nmero
return suma
a
1 2 3
print sumatorio a

o as:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4
5
6
7

def sumatorio lista


suma
0
for nmero in lista
suma
nmero
return suma
print sumatorio

En cualquiera de los dos casos, el parmetro lista toma el valor


argumento suministrado en la llamada:
1 2 3

lista

sumatorio

3 , que es el

Sumatorios

Has aprendido a calcular sumatorios con bucles. Desde la versin 2.3, Python ofrece una forma
mucho ms cmoda de calcular sumatorios: la funcin predefinida sum, que recibe una lista de valores
y devuelve el resultado de sumarlos.
La funcin sum (y tambin la que hemos diseado, sumatorio), no solo suma elementos de listas:
tambin suma elementos de una sucesin cualquiera. Cmo usarla para calcular el sumatorio de los
100 primeros nmeros naturales? Muy fcil: pasndole una secuencia con esos nmeros, algo que
resulta trivial si usas range:
Ten cuidado. No es la forma ms eficiente de sumar los 100 primeros nmeros. Recuerda que la
suma de los n primeros nmeros se puede calcular directamente como n (n + 1)/2:

267
Disea una funcin que calcule el sumatorio de la diferencia entre nmeros contiguos
en una lista. Por ejemplo, para la lista 1 3 6 10 devolver 9, que es 2 + 3 + 4 (el 2 resulta
de calcular 3 1, el 3 de calcular 6 3 y el 4 de calcular 10 6).
Estudiemos otro ejemplo: una funcin que recibe una lista de nmeros y devuelve el valor
de su mayor elemento.
lista

mximo

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

mayor elemento de lista

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

La idea bsica es sencilla: recorrer la lista e ir actualizando el valor de una variable auxiliar
que, en todo momento, contendr el mximo valor visto hasta ese momento.
1
2
3
4
5

def mximo lista


for elemento in lista
if elemento
candidato
candidato
elemento
return candidato

Nos falta inicializar la variable candidato. Con qu valor? Podramos pensar en inicializarla
con el menor valor posible. De ese modo, cualquier valor de la lista ser mayor que l y es seguro
que su valor se modificar tan pronto empecemos a recorrer la lista. Pero hay un problema: no
sabemos cul es el menor valor posible. Una buena alternativa es inicializar candidato con el
valor del primer elemento de la lista. Si ya es el mximo, perfecto, y si no lo es, ms tarde se
modificar candidato.
1
2
3
4
5
6

def mximo lista


candidato
lista 0
for elemento in lista
if elemento
candidato
candidato
elemento
return candidato

268

Haz una traza de la llamada mximo

10

Ya est? An no. Qu pasa si se proporciona una lista vaca como entrada? La lnea 2
provocar un error de tipo IndexError, pues en ella intentamos acceder al primer elemento de
la lista. . . y la lista vaca no tiene ningn elemento. Un objetivo es, pues, evitar ese error. Pero,
en cualquier caso, algo hemos de devolver como mximo elemento de una lista, y qu valor
podemos devolver como mximo elemento de una lista vaca? Mmmm. A bote pronto, tenemos dos
posibilidades:
Devolver un valor especial, como el valor 0. Mejor no. Tiene un serio inconveniente: cmo
5 0
4 , que es un cero legtimo, del mximo de ?
distinguir el mximo de 3

O devolver un valor muy especial, como el valor None. Que qu es None? None
significa en ingls ninguno y es un valor predefinido en Python que se usa para denotar
ausencia de valor. Como el mximo de una lista vaca no existe, parece acertado devolver
la ausencia de valor como mximo de sus miembros.

Nos inclinamos por esta segunda opcin. En adelante, usaremos None siempre que queramos
referirnos a un valor muy especial: a la ausencia de valor.
1
2

3
4
5
6
7
8
9

def mximo lista


if len lista
0
candidato
lista 0
for elemento in lista
if elemento
candidato
candidato
elemento
else
candidato
None
return candidato

269
Disea una funcin que, dada una lista de nmeros enteros, devuelva el nmero de
series que hay en ella. Llamamos serie a todo tramo de la lista con valores idnticos.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Por ejemplo, la lista 1 1 8 8 8 8 0 0 0 2 10 10 tiene 5 series (ten en


cuenta que el 2 forma parte de una serie de un solo elemento).

270
Disea una funcin que diga en qu posicin empieza la serie ms larga de una
lista. En el ejemplo del ejercicio anterior, la serie ms larga empieza en la posicin 2 (que es
el ndice donde aparece el primer 8). (Nota: si hay dos series de igual longitud y esta es la
mayor, debes devolver la posicin de la primera de las series. Por ejemplo, para 8 2 2
9 9 debers devolver la posicin 1).

271
Haz una funcin que reciba una lista de nmeros y devuelva la media de dichos
nmeros. Ten cuidado con la lista vaca (su media es cero).

272
una lista.

Disea una funcin que calcule el productorio de todos los nmeros que componen

273
Disea una funcin que devuelva el valor absoluto de la mxima diferencia entre dos
elementos consecutivos de una lista. Por ejemplo, el valor devuelto para la lista 1 10 2 6
2 0 es 9, pues es la diferencia entre el valor 1 y el valor 10.

274
Disea una funcin que devuelva el valor absoluto de la mxima diferencia entre
cualquier par de elementos de una lista. Por ejemplo, el valor devuelto para la lista 1 10 2
6 8 2 0 es 10, pues es la diferencia entre el valor 10 y el valor 0. (Pista: te puede convenir
conocer el valor mximo y el valor mnimo de la lista).
275
Define una funcin que, dada una cadena x, devuelva otra cuyo contenido sea el
resultado de concatenar 6 veces x consigo misma.

276
Disea una funcin que, dada una lista de cadenas, devuelva la cadena ms larga.
Si dos o ms cadenas miden lo mismo y son las ms largas, la funcin devolver una cualquiera
de ellas.
, la funcin devolver la ca(Ejemplo: dada la lista
).
dena

277
Disea una funcin que, dada una lista de cadenas, devuelva una lista con todas las
cadenas ms largas, es decir, si dos o ms cadenas miden lo mismo y son las ms largas, la lista
las contendr a todas.
, la funcin devolver la lista
(Ejemplo: dada la lista
).
de dos elementos
278
Disea una funcin que reciba una lista de cadenas y devuelva el prefijo comn ms
es el prefijo comn ms largo de esta lista:
largo. Por ejemplo, la cadena

6.2.2.

Definicin y uso de funciones con varios parmetros

No todas las funciones tienen un solo parmetro. Vamos a definir ahora una con dos parmetros: una funcin que devuelve el valor del rea de un rectngulo dadas su altura y su
anchura:
rea_rectngulo

altura

anchura

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

producto de altura por anchura

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Importaciones, definiciones de funcin y programa principal

Los programas que disees a partir de ahora tendrn tres tipos de lnea: importacin de mdulos
(o funciones y variables de mdulos), definicin de funciones y sentencias del programa principal. En
principio puedes alternar lneas de los tres tipos. Mira este programa, por ejemplo,
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

def cuadrado x
return x 2

mivector
for i in range 3
mivector append float input

def suma_cuadrados vector


suma
0
for elemento in vector
suma
cuadrado elemento
return suma
s

suma_cuadrados mivector

from math import sqrt


print

sqrt s

En l se alternan definiciones de funcin, importaciones de funciones y sentencias del programa


principal, as que resulta difcil hacerse una idea clara de qu hace el programa. No disees as tus
programas.

Importaciones, definiciones de funcin y programa principal (y II)

Esta otra versin del programa anterior pone en primer lugar las importaciones, a continuacin,
las funciones y, al final, de un tirn, las sentencias que conforman el programa principal:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

from math import sqrt


def cuadrado x
return x 2

def suma_cuadrados vector


suma
0
for elemento in vector
suma
cuadrado elemento
return suma
Programa principal
mivector
for i in range 3
mivector append float input
s
suma_cuadrados mivector
print

sqrt s

Es mucho ms legible. Te recomendamos que sigas siempre esta organizacin en tus programas.
Recuerda que la legibilidad de los programas es uno de los objetivos del programador.

1
2

def rea_rectngulo altura anchura


return altura
anchura

Observa que los diferentes parmetros de una funcin deben separarse por comas. Al usar
la funcin, los argumentos tambin deben separarse por comas:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4

def rea_rectngulo altura anchura


return altura
anchura
print rea_rectngulo 3

rea_rectngulo

12

279
Define una funcin que, dado el valor de los tres lados de un tringulo, devuelva la
longitud de su permetro.

280
Define una funcin que, dados dos parmetros b y x, devuelva el valor de logb (x), es
decir, el logaritmo en base b de x.

281
Disea una funcin que devuelva la solucin de la ecuacin lineal ax + b = 0 dados
a y b. Si la ecuacin tiene infinitas soluciones o no tiene solucin alguna, la funcin lo detectar
y devolver el valor None.

282
Disea una funcin que calcule bi=a i dados a y b. Si a es mayor que b, la funcin
devolver el valor 0.

283
Disea una funcin que calcule bi=a i dados a y b. Si a es mayor que b, la funcin
devolver el valor 0. Si 0 se encuentra entre a y b, la funcin devolver tambin el valor cero,
pero sin necesidad de iterar en un bucle.

284
Define
una funcin llamada raz_n_sima que devuelva el valor de n x. (Nota: re
cuerda que n x es x 1/n ).

285
Haz una funcin que reciba un nmero de DNI y una letra. La funcin devolver
True si la letra corresponde a ese nmero de DNI, y False en caso contrario. La funcin debe
llamarse comprueba_letra_dni.
Si lo deseas, puedes llamar a la funcin letra_dni, desarrollada en el ejercicio 260, desde
esta nueva funcin.

286
Disea una funcin que diga (mediante la devolucin de True o False) si dos nmeros
son amigos. Dos nmeros son amigos si la suma de los divisores del primero (excludo l) es
igual al segundo y viceversa.

6.2.3.

Definicin y uso de funciones sin parmetros

Vamos a considerar ahora cmo definir e invocar funciones sin parmetros. En realidad hay
poco que decir: lo nico que debes tener presente es que es obligatorio poner parntesis a
continuacin del identificador, tanto al definir la funcin como al invocarla.
En el siguiente ejemplo se define y usa una funcin que lee de teclado un nmero entero:
1
2
3
4

def lee_entero
return int input
a

lee_entero

Recuerda: al llamar a una funcin los parntesis no son opcionales. Podemos representar
esta funcin como una caja que proporciona un dato de salida sin ningn dato de entrada:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

lee_entero

nmero entero

Mmmm. Te hemos dicho que la funcin no recibe dato alguno y debes estar pensando que te
hemos engaado, pues la funcin lee un dato de teclado. Quiz este diagrama represente mejor
la entrada/salida de la funcin:
lee_entero

nmero entero

De acuerdo; pero no te equivoques: el dato ledo de teclado no es un dato que el programa


suministre a la funcin mediante un parmetro.
Parmetros o teclado

Un error frecuente al disear funciones consiste en tratar de obtener la informacin directamente


de teclado. No es que est prohibido, pero es ciertamente excepcional que una funcin obtenga
la informacin de ese modo. Cuando te pidan disear una funcin que recibe uno o ms datos, se
sobreentiende que debes suministrarlos como argumentos en la llamada, no leerlos de teclado. Cuando
queramos que la funcin lea algo de teclado, lo diremos explcitamente.
Insistimos, y esta vez ilustrando el error con un ejemplo. Imagina que te piden que disees una
funcin que diga si un nmero es par devolviendo True si es as y False en caso contrario. Te piden
una funcin como esta:
def es_par n
return n

1
2

def es_par
n
int input
return n
2

Muchos programadores novatos escriben errneamente una funcin como esta otra:

1
2
3

Est mal. Escribir esa funcin as demuestra, cuando menos, falta de soltura en el diseo de
funciones. Si hubisemos querido una funcin como esa, te hubisemos pedido una funcin que lea
de teclado un nmero entero y devuelva True si es par y False en caso contrario.

1
2
3
4
5
6
7

Esta otra funcin lee un nmero de teclado y se asegura de que sea positivo:

def lee_entero_positivo
nmero
int input
while nmero
0
nmero
int input
return nmero
a

lee_entero_positivo

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Y esta versin muestra por pantalla un mensaje informativo cuando el usuario se equivoca:
1
2
3
4
5
6
7
8

def lee_entero_positivo
nmero
int input
while nmero
0
print
nmero
int input
return nmero
a

lee_entero_positivo

Los parntesis son necesarios

Un error tpico de los aprendices es llamar a las funciones sin parmetros omitiendo los parntesis,
pues les parecen innecesarios. Veamos qu ocurre en tal caso:

Como puedes ver, el ltimo resultado no es la impresin del mensaje


, sino otro encerrado
entre smbolos de menor y mayor. Estamos llamando incorrectamente a la funcin: saluda, sin parntesis, es un objeto Python ubicado en la direccin de memoria que se muestra en hexadecimal
(nmero que puede ser distinto con cada ejecucin).
Ciertas tcnicas avanzadas de programacin sacan partido del uso del identificador de la funcin
sin parntesis, pero an no ests preparado para entender cmo y por qu. El cuadro Un mtodo de
integracin genrico te proporcionar ms informacin.

Una posible aplicacin de la definicin de funciones sin argumentos es la presentacin de


mens con seleccin de opcin por teclado. Esta funcin, por ejemplo, muestra un men con tres
opciones, pide al usuario que seleccione una y se asegura de que la opcin seleccionada es
vlida. Si el usuario se equivoca, se le informa por pantalla del error:
1
2
3
4
5
6
7
8
9

10
11

def men
opcin
while not opcin
print
print
print
print
opcin
input
if not opcin
print
return opcin

and opcin

and opcin

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

men

letra con opcin escogida

Hemos dibujado una pantalla para dejar claro que uno de los cometidos de esta funcin es
mostrar informacin por pantalla (las opciones del men).
Si en nuestro programa principal se usa con frecuencia el men, bastar con efectuar las
correspondientes llamadas a la funcin men
y almacenar la opcin seleccionada en una
variable. As:
1

accin

men

287

Funciona esta otra versin de men?

La variable accin contendr la letra seleccionada por el usuario. Gracias al control que
, una
o una
.
efecta la funcin, estaremos seguros de que dicha variable contiene una
1
2
3
4
5
6
7
8
9

10
11

def men
opcin
while len opcin
print
print
print
print
opcin
input
if len opcin
print
return opcin

1 or opcin not in

1 or opcin not in

288
En un programa que estamos diseando preguntamos al usuario numerosas cuestiones
que requieren una respuesta afirmativa o negativa. Disea una funcin llamada s_o_no que
reciba una cadena (la pregunta). Dicha cadena se mostrar por pantalla y se solicitar al
usuario que responda. Solo aceptaremos como respuestas vlidas
,
,
,
,
,
,
,
, las cuatro primeras para respuestas afirmativas y las cuatro ltimas para
respuestas negativas. Cada vez que el usuario se equivoque, en pantalla aparecer un mensaje
que le recuerde las respuestas aceptables. La funcin devolver True si la respuesta es afirmativa,
y False en caso contrario.

Hay funciones sin parmetros que puedes importar de mdulos. Una que usaremos en varias
ocasiones es random (en ingls random significa aleatorio). La funcin random, definida en
el mdulo que tiene el mismo nombre, devuelve un nmero al azar mayor o igual que 0.0 y menor
que 1.0.
random

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

nmero x tal que 0 x < 1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Veamos un ejemplo de uso de la funcin:

Ves? La funcin se invoca sin argumentos (entre los parntesis no hay nada) y cada vez que
lo hacemos obtenemos un resultado diferente. Qu inters tiene una funcin tan extraa? Una
funcin capaz de generar nmeros aleatorios encuentra muchos campos de aplicacin: estadstica,
videojuegos, simulacin, etc. Dentro de poco le sacaremos partido.

289
Disea una funcin sin argumentos que devuelva un nmero aleatorio mayor o igual
que 0.0 y menor que 10.0. Puedes llamar a la funcin random desde tu funcin.
290
Disea una funcin sin argumentos que devuelva un nmero aleatorio mayor o igual
que 10.0 y menor que 10.0.

291
Para disear un juego de tablero nos vendr bien disponer de un dado electrnico. Escribe una funcin Python sin argumentos llamada dado que devuelva un nmero entero
aleatorio entre 1 y 6.

6.2.4.

Procedimientos: funciones sin devolucin de valor

No todas las funciones devuelven un valor. Una funcin que no devuelve un valor se denomina
procedimiento. Y para qu sirve una funcin que no devuelve nada? Bueno, puede, por ejemplo,
mostrar mensajes o resultados por pantalla. No te equivoques: mostrar algo por pantalla no es
devolver nada. Mostrar un mensaje por pantalla es un efecto secundario.
Vemoslo con un ejemplo. Vamos a implementar ahora un programa que solicita al usuario
un nmero y muestra por pantalla todos los nmeros perfectos entre 1 y dicho nmero.
m

tabla_perfectos

Reutilizaremos la funcin es_perfecto que definimos antes en este mismo captulo. Como la
solucin no es muy complicada, te la ofrecemos completamente desarrollada:
1
2
3
4
5
6
7
8

def es_perfecto n
Averigua si el nmero n es o no es perfecto.
sumatorio
0
for i in range 1 n
if n
i
0
sumatorio
i
return sumatorio
n
def tabla_perfectos m

Muestra todos los nmeros perfectos entre 1 y m.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

for i in range 1 m 1
if es_perfecto i
print i

10
11
12
13
14

nmero
int input
tabla_perfectos nmero

Fjate en que la funcin tabla_perfectos no devuelve nada (no hay sentencia return): es un
procedimiento. Tambin resulta interesante la lnea 10: como es_perfecto devuelve True o False,
podemos utilizarla directamente como condicin del if.
Condicionales que trabajan directamente con valores lgicos

Ciertas funciones devuelven directamente un valor lgico. Considera, por ejemplo, esta funcin, que
nos dice si un nmero es o no es par:
1
2

def es_par n
return n

Si una sentencia condicional toma una decisin en funcin de si un nmero es par o no, puedes
codificar as la condicin:
1
2

if es_par n

Observa que no hemos usado comparador alguno en la condicin del if. Por qu? Porque la
funcin es_par n devuelve True o False directamente. Los programadores primerizos tienen tendencia
a codificar la misma condicin as:
1
2

if es_par n

True

Es decir, comparan el valor devuelto por es_par con el valor True, pues les da la sensacin de que
un if sin comparacin no est completo. No pasa nada si usas la comparacin, pero es innecesaria.
Es ms, si no usas la comparacin, el programa es ms legible: la sentencia condicional se lee
directamente como si n es par en lugar de si n es par es cierto, que es un extrao circunloquio.
Si deseas comprobar que el nmero es impar, puedes hacerlo as:
1
2

1
2

if not es_par n

Es muy legible: si no es par n. Los programadores que estn empezando escriben:

if es_par n

False

que se lee como si n es par es falso. Peor, no?


Acostmbrate a usar la versin que no usa operador de comparacin. Es ms legible.

292
Disea un programa que, dado un nmero n, muestre por pantalla todas las parejas
de nmeros amigos menores que n. La impresin de los resultados debe hacerse desde un
procedimiento.
Dos nmeros amigos solo debern aparecer una vez por pantalla. Por ejemplo, 220 y 284 son
amigos: si aparece el mensaje
, no podr aparecer el mensaje
, pues es redundante.
Debes disear una funcin que diga si dos nmeros son amigos y un procedimiento que
muestre la tabla.
293

Implementa un procedimiento Python tal que, dado un nmero entero, muestre por

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

pantalla sus cifras en orden inverso. Por ejemplo, si el procedimiento recibe el nmero 324,
mostrar por pantalla el 4, el 2 y el 3 (en lneas diferentes).

294
Disea una funcin es_primo que determine si un nmero es primo (devolviendo True)
o no (devolviendo False). Disea a continuacin un procedimiento muestra_primos que reciba
un nmero y muestre por pantalla todos los nmeros primos entre 1 y dicho nmero.

Y qu ocurre si utilizamos un procedimiento como si fuera una funcin con devolucin de valor? Podemos hacer la prueba. Asignemos a una variable el resultado de llamar a tabla_perfectos
y mostremos por pantalla el valor de la variable:
1
2
3
4
5
6
7
8
9

10
11
12
13
14

def es_perfecto n
Averigua si el nmero n es o no es perfecto.
sumatorio
0
for i in range 1 n
if n
i
0
sumatorio
i
return sumatorio
n

def tabla_perfectos m
Muestra todos los nmeros perfectos entre 1 y m.
for i in range 1 m 1
if es_perfecto i
print i
resultado
tabla_perfectos 100
print resultado

Por pantalla aparece lo siguiente:

Mira la ltima lnea, que muestra el contenido de resultado. Recuerda que Python usa None
para indicar un valor nulo o la ausencia de valor, y una funcin que no devuelve nada devuelve
la ausencia de valor, no?
Cambiamos de tercio. Supn que mantenemos dos listas con igual nmero de elementos. Una
de ellas, llamada alumnos, contiene una serie de nombres y la otra, llamada notas, una serie de
nmeros flotantes entre 0.0 y 10.0. En notas guardamos la calificacin obtenida por los alumnos
cuyos nombres estn en alumnos: la nota notas i corresponde al estudiante alumnos i . Una
posible configuracin de las listas sera esta:
1
2

alumnos
notas

10

5.5

2.0

8.5

7.0

De acuerdo con ella, el alumno Pau Lpez, por ejemplo, fue calificado con un 5.5.
Nos piden disear un procedimiento que recibe como datos las dos listas y una cadena con
el nombre de un estudiante. Si el estudiante pertenece a la clase, el procedimiento imprimir
su nombre y nota en pantalla. Si no es un alumno incluido en la lista, se imprimir un mensaje
que lo advierta.
muestra_nota_de_alumno
alumnos
notas
alumno_buscado

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Valor de retorno o pantalla

Te hemos mostrado de momento que es posible imprimir informacin directamente por pantalla
desde una funcin (o procedimiento). Ojo: solo lo hacemos cuando el propsito de la funcin es mostrar
esa informacin. Muchos aprendices que no han comprendido bien el significado de la sentencia return,
la sustituyen por una sentencia print. Mal. Cuando te piden que disees una funcin que devuelva
un valor, te piden que lo haga con la sentencia return, que es la nica forma vlida (que conoces) de
devolver un valor. Mostrar algo por pantalla no es devolver ese algo. Cuando quieran que muestres
algo por pantalla, te lo dirn explcitamente.
Supn que te piden que disees una funcin que reciba un entero y devuelva su ltima cifra. Te
piden esto:
1
2

1
2

def ltima_cifra nmero


return nmero
10
No te piden esto otro:

def ltima_cifra nmero


print nmero
10

Fjate en que la segunda definicin hace que la funcin no pueda usarse en expresiones como
esta:
1

1
2
3

ltima_cifra 10293

Como ltima_cifra no devuelve nada, qu valor se est sumando a 1 y guardando en a?


Ah! An se puede hace peor. Hay quien define la funcin as:

def ltima_cifra
nmero
int input
print nmero
10

No solo demuestra no entender qu es el valor de retorno; adems, demuestra que no tiene ni idea
de lo que es el paso de parmetros. Evita dar esa impresin: lee bien lo que se pide y usa parmetros
y valor de retorno a menos que se te diga explcitamente lo contrario. Lo normal es que la mayor
parte de las funciones produzcan datos (devueltos con return) a partir de otros datos (obtenidos con
parmetros) y que el programa principal o funciones muy especficas lean de teclado y muestren por
pantalla.

1
2
3
4
5
6
7
8

Aqu tienes una primera versin:

def muestra_nota_de_alumno alumnos notas


encontrado
False
for i in range len alumnos
if alumnos i
alumno_buscado
print alumno_buscado notas i
encontrado
True
if not encontrado
print

alumno_buscado

def muestra_nota_de_alumno alumnos notas


encontrado
False
for i in range len alumnos
if alumnos i
alumno_buscado
print alumno_buscado notas i
encontrado
True

alumno_buscado

format alumno_buscado

Lo podemos hacer ms eficientemente: cuando hemos encontrado al alumno e impreso el


correspondiente mensaje, no tiene sentido seguir iterando:
1
2
3
4
5
6

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

break
if not encontrado
print

7
8
9

1
2
3
4
5
6

Esta otra versin es an ms breve3 :

def muestra_nota_de_alumno alumnos notas


for i in range len alumnos
if alumnos i
alumno_buscado
print alumno_buscado notas i
return
print

format alumno_buscado
alumno_buscado
format alumno_buscado

Los procedimientos aceptan el uso de la sentencia return aunque, eso s, sin expresin
alguna a continuacin (recuerda que los procedimientos no devuelven valor alguno). Qu hace
esa sentencia? Aborta inmediatamente la ejecucin de la llamada a la funcin. Es, en cierto
modo, similar a una sentencia break en un bucle, pero asociada a la ejecucin de una funcin.
295

En el problema de los alumnos y las notas, se pide:

1) Disear un procedimiento que reciba las dos listas y muestre por pantalla el nombre de todos
los estudiantes que aprobaron el examen.
2) Disear una funcin que reciba la lista de notas y devuelva el nmero de aprobados.

3) Disear un procedimiento que reciba las dos listas y muestre por pantalla el nombre de todos
los estudiantes que obtuvieron la mxima nota.
4) Disear un procedimiento que reciba las dos listas y muestre por pantalla el nombre de todos
los estudiantes cuya calificacin es igual o superior a la calificacin media.
5) Disear una funcin que reciba las dos listas y un nombre (una cadena); si el nombre est
en la lista de estudiantes, devolver su nota, si no, devolver None.

296
Tenemos los tiempos de cada ciclista y etapa para los participantes en la ltima vuelta
ciclista local. La lista ciclistas contiene una serie de nombres. La matriz tiempos tiene una fila
por cada ciclista, en el mismo orden con que aparecen en ciclistas. Cada fila tiene el tiempo en
segundos (un valor flotante) invertido en cada una de las 5 etapas de la carrera. Complicado?
Quizs te ayude este ejemplo de lista ciclistas y de matriz tiempos para 3 corredores.
1
2
3
4

ciclistas
tiempo

10092.0 12473.1 13732.3 10232.1 10332.3


11726.2 11161.2 12272.1 11292.0 12534.0
10193.4 10292.1 11712.9 10133.4 11632.0

En el ejemplo, el ciclista Joan Beltran invirti 11161.2 segundos en la segunda etapa.


Se pide:

Una funcin que reciba la lista y la matriz y devuelva el ganador de la vuelta (aquel cuya
suma de tiempos en las 5 etapas es mnima).
Una funcin que reciba la lista, la matriz y un nmero de etapa y devuelva el nombre del
ganador de la etapa.
Un procedimiento que reciba la lista, la matriz y muestre por pantalla el ganador de cada
una de las etapas.

3 . . . aunque puede disgustar a los puristas de la programacin estructurada. Segn estos, solo debe haber un punto
de salida de la funcin: el final de su cuerpo. Salir directamente desde un bucle les parece que dificulta la comprensin
del programa.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6.2.5.

Funciones que devuelven varios valores mediante una lista

En principio una funcin puede devolver un solo valor con la sentencia return. Pero sabemos
que una lista es un objeto que contiene una secuencia de valores. Si devolvemos una lista
podemos, pues, devolver varios valores.
Por ejemplo, una funcin puede devolver al mismo tiempo el mnimo y el mximo de 3 nmeros:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

def minmax a b c
Calcular el mnimo
if a
b
if a
c
min
a
else
min
c
else
if b
c
min
b
else
min
c

Calcular el mximo
if a
b
if a
c
max
a
else
max
c
else
if b
c
max
b
else
max
c
return

min

max

Podemos representar a la funcin con este diagrama:


a
b
c

minmax

mnimo de los tres


mximo de los tres

aunque quiz sea ms apropiado este otro:


a
b
c

1
2
3
4
5

minmax

lista con mnimo y mximo

Cmo podramos llamar a esa funcin? Una posibilidad es esta:

def minmax a b c
Calcular el mnimo
if a
b
if a
c
min
a

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6
7
8
9

10

else

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

else
if b

else

min

min

c
min

Calcular el mximo
if a
b
if a
c
max
a
else
max
c
else
if b
c
max
b
else
max
c
return

min

a
minmax 10
print
print

max

Y esta es otra:

a 0
a 1

def minmax a b c
Calcular el mnimo
if a
b
if a
c
min
a
else
min
c
else
if b
c
min
b
else
min
c

Calcular el mximo
if a
b
if a
c
max
a
else
max
c
else
if b
c
max
b
else
max
c
return

mnimo
print
print

min

mximo

max

minmax 10
mnimo
mximo

En este segundo caso hemos asignado una lista a otra. Qu significa eso para Python?

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Pues que cada elemento de la lista a la derecha del igual debe asignarse a cada variable de la
lista a la izquierda del igual.
1
2
3
4

297

a
b

1
2
a b
print a

Qu aparecer por pantalla al ejecutar este programa?


b

298
Disea una funcin que reciba una lista de enteros y devuelva los nmeros mnimo
y mximo de la lista simultneamente.

299
Disea una funcin que reciba los tres coeficientes de una ecuacin de segundo grado
de la forma ax 2 + bx + c = 0 y devuelva una lista con sus soluciones reales. Si la ecuacin solo
tiene una solucin real, devuelve una lista con dos copias de la misma. Si no tiene solucin real
alguna o si tiene infinitas soluciones, devuelve una lista con dos copias del valor None.

300
Disea una funcin que reciba una lista de palabras (cadenas) y devuelva, simultneamente, la primera y la ltima palabras segn el orden alfabtico.
Inicializacin mltiple e intercambio

Ahora que sabes que es posible asignar valores a varias variables simultneamente, puedes simplificar algunos programas que empiezan con la inicializacin de varias variables. Por ejemplo, esta
serie de asignaciones:
1
2
3

a
b
c

1
2
3

puede reescribirse as:


a

Mmmm. An podemos escribirlo ms brevemente:

Por qu no hacen falta los corchetes? Porque en este caso estamos usando una estructura
ligeramente diferente: una tupla. Una tupla es una lista inmutable y no necesita ir encerrada entre
corchetes.
As pues, el intercambio del valor de dos variables puede escribirse as:
1

Cmodo, no crees?

6.3.

Variables locales y variables globales

Observa que en el cuerpo de las funciones es posible definir y usar variables. Vamos a
estudiar con detenimiento algunas propiedades de las variables definidas en el cuerpo de una
funcin y en qu se diferencian de las variables que definimos fuera de cualquier funcin, es
decir, en el denominado programa principal.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Empecemos con un ejemplo. Definamos una funcin que, dados los tres lados de un tringulo,
devuelva el valor de su rea. Recuerda que si a, b y c son dichos lados, el rea del tringulo es

s(s a)(s b)(s c),

donde s = (a + b + c)/2.

1
2
3
4
5

La funcin se define as:

a
b
c

rea_tringulo

rea del tringulo

from math import sqrt

def rea_tringulo a b c
s
a
b
c
2
return sqrt s
s a

s b

s c

s b

s c

La lnea 4, en el cuerpo de la funcin, define la variable s asignndole un valor que es


instrumental para el clculo del rea del tringulo, es decir, que no nos interesa por s mismo,
sino por ser de ayuda para obtener el valor que realmente deseamos calcular: el que resulta de
evaluar la expresin de la lnea 5.
La funcin rea_tringulo se usa como cabe esperar:
1
2
3
4
5
6
7

from math import sqrt

def rea_tringulo a b c
s
a
b
c
2
return sqrt s
s a
print rea_tringulo 1

2.5

Ahora viene lo importante: la variable s solo existe en el cuerpo de la funcin. Fuera de dicho
cuerpo, s no est definida. El siguiente programa provoca un error al ejecutarse porque intenta
acceder a s desde el programa principal:
E
1
2
3
4
5
6
7
8

from math import sqrt

def rea_tringulo a b c
s
a
b
c
2
return sqrt s
s a
print rea_tringulo 1
print s

2.5

s b

s c

Cuando se ejecuta ocurre esto:

La primera lnea mostrada en pantalla es el resultado de ejecutar la lnea 7 del programa.


La lnea 7 incluye una llamada a rea_tringulo, as que el flujo de ejecucin ha pasado por la
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

lnea 4 y s se ha creado correctamente. De hecho, se ha accedido a su valor en la lnea 5 y no


se ha producido error alguno. Sin embargo, al ejecutar la lnea 8 se ha producido un error por
intentar mostrar el valor de una variable inexistente: s. La razn es que s se ha creado en la
lnea 4 y se ha destruido tan pronto ha finalizado la ejecucin de rea_tringulo.
Las variables que solo existen en el cuerpo de una funcin se denominan variables locales.
En contraposicin, el resto de variables se llaman variables globales.
Tambin los parmetros formales de una funcin se consideran variables locales, as que no
puedes acceder a su valor fuera del cuerpo de la funcin.
Fjate en este otro ejemplo:
E
1
2
3
4
5
6
7
8

from math import sqrt

def rea_triangulo a b c
s
a
b
c
2
return sqrt s
s a
print rea_tringulo 1
print a

2.5

s b

s c

Y cundo se crean a, b y c? Con qu valores? Cuando llamamos a la funcin con, por ejemplo,
rea_tringulo 1 3 2.5 , ocurre lo siguiente: los parmetros a, b y c se crean como variables
locales en la funcin y apuntan a los valores 1, 3 y 2.5, respectivamente. Se inicia entonces la
ejecucin del cuerpo de rea_tringulo hasta llegar a la lnea que contiene el return. El valor
que resulta de evaluar la expresin que sigue al return se devuelve como resultado de la llamada
a la funcin. Al acabar la ejecucin de la funcin, las variables locales a, b y c dejan de existir
(del mismo modo que deja de existir la variable local s).
Para ilustrar los conceptos de variables locales y globales con mayor detalle vamos a utilizar
la funcin rea_tringulo en un programa un poco ms complejo.
Imagina que queremos ayudarnos con un programa en el clculo del rea de un tringulo de
lados a, b y c y en el clculo del ngulo (en grados) opuesto al lado a.
b

El ngulo se calcula con la frmula

180
=
arcsin

2s
bc

donde s es el rea del tringulo y arcsin es la funcin arco-seno. (La funcin matemtica arcsin
est definida en el mdulo math con el identificador asin).
Analiza este programa en el que hemos destacado las diferentes apariciones del identificador s:
1
2
3
4
5
6
7
8
9

10

from math import sqrt

asin

def rea_tringulo a b c
s
a
b
c
2
return sqrt s
s a

pi

s b

def ngulo_alfa a b c
s
rea_tringulo a b c
return 180
pi
asin 2
s

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

s c
b c

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

def men
opcin
0
while opcin
1 and opcin
print
print
opcin
int input
return opcin
lado1
lado2
lado3
s

if s

else

float input
float input
float input

men

1
resultado
resultado

print
print

rea_tringulo lado1
ngulo_alfa lado1

lado2

lado2

s
resultado

lado3

lado3

Hagamos una traza del programa para esta ejecucin:

La lnea 1 importa las funciones sqrt (raz cuadrada) y asin (arcoseno) y la variable pi
(aproximacin de ).

Las lneas 35 ensean a Python cmo se realiza un clculo determinado al que denominamos rea_tringulo y que necesita tres datos de entrada.
Las lneas 79 ensean a Python cmo se realiza un clculo determinado al que denominamos ngulo_alfa y que tambin necesita tres datos de entrada.

Las lneas 1117 definen la funcin men. Es una funcin sin parmetros cuyo cometido
es mostrar un men con dos opciones, esperar a que el usuario escoja una y devolver la
opcin seleccionada.

Las lneas 1921 leen de teclado el valor (flotante) de tres variables: lado1, lado2 y lado3.
En nuestra ejecucin, las variables valdrn 5.0, 4.0 y 3.0, respectivamente.
La lnea 23 contiene una llamada a la funcin men. En este punto, Python memoriza que
se encontraba ejecutando la lnea 23 cuando se produjo una llamada a funcin y deja su
ejecucin en suspenso. Salta entonces a la lnea 12, es decir, al cuerpo de la funcin men.
Sigamos el flujo de ejecucin en dicho cuerpo:
Se ejecuta la lnea 12. La variable local opcin almacena el valor 0.

En la lnea 13 hay un bucle while. Es opcin distinto de 1 y de 2? S. Entramos,


pues, en el bloque del bucle: la siguiente lnea a ejecutar es la 14.
En la lnea 14 se imprime un texto en pantalla (el de la primera opcin).

En la lnea 15 se imprime otro texto en pantalla (el de la segunda opcin).

En la lnea 16 se lee el valor de opcin de teclado, que en esta ejecucin es 1.

Como el bloque del bucle no tiene ms lneas, volvemos a la lnea 13. Nos volvemos
a preguntar es opcin distinto de 1 y a la vez distinto de 2? No: opcin vale 1. El
bucle finaliza y saltamos a la lnea 17.

En la lnea 17 se devuelve el valor 1, que es el valor de opcin, y la variable local


opcin se destruye.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Qu lnea se ejecuta ahora? La ejecucin de la llamada a la funcin ha finalizado, as que


Python regresa a la lnea desde la que se produjo la llamada (la lnea 23), cuya ejecucin
haba quedado en suspenso. El valor devuelto por la funcin (el valor 1) se almacena ahora
en una variable llamada s.
La lnea 25 compara el valor de s con el valor 1 y, como son iguales, la siguiente lnea a
ejecutar es la 26 (las lneas 27 y 28 no se ejecutarn).

La lnea 26 asigna a resultado el resultado de invocar a rea_tringulo con los valores


5.0, 4.0 y 3.0. Al invocar la funcin, el flujo de ejecucin del programa salta a su cuerpo
y la ejecucin de la lnea 26 queda en suspenso.

Saltamos, pues, a la lnea 4, con la que empieza el cuerpo de la funcin rea_tringulo.


Ojo!, los parmetros a, b y c se crean como variables locales y toman los valores
5.0, 4.0 y 3.0, respectivamente (son los valores de lado1, lado2 y lado3). En la lnea
4 se asigna a s, una nueva variable local, el valor que resulte de evaluar a
b
c 2, es decir, 6.0.

En la lnea 5 se devuelve el resultado de evaluar sqrt s


s a
s b
s c ,
que tambin es, casualmente, 6.0. Tanto s como los tres parmetros dejan de existir.

Volvemos a la lnea 26, cuya ejecucin estaba suspendida a la espera de conocer el valor
de la llamada a rea_tringulo. El valor devuelto, 6.0, se asigna a resultado.

La lnea 30 muestra por pantalla el valor actual de s. . . y qu valor es ese? Al ejecutar


la lnea 23 le asignamos a s el valor 1, pero al ejecutar la lnea 4 le asignamos el valor
6.0! Debe salir por pantalla, pues, un 6.0? No: la lnea 23 asign el valor 1 a la variable
global s. El 6.0 de la lnea 4 se asign a la variable s local a la funcin rea_tringulo,
que ya no existe.
Finalmente, el valor de resultado se muestra por pantalla en la lnea 31.

Observa que llamamos s a dos variables diferentes y que cada una de ellas recuerda su
valor sin interferir con el valor de la otra. Si accedemos a s desde rea_tringulo, accedemos a
la s local a rea_tringulo. Si accedemos a s desde fuera de cualquier funcin, accedemos a la
s global.
Puede que te parezca absurdo que Python distinga entre variables locales y variables globales, pero lo cierto es que disponer de estos dos tipos de variable es de gran ayuda. Piensa en qu
ocurrira si la variable s de la lnea 4 fuese global: al acabar la ejecucin de rea_tringulo, s
recordara el valor 6.0 y habra olvidado el valor 1. El texto impreso en la lnea 30 sera errneo,
. Disponer de variables locales permite
pues se leera as:
asegurarse de que las llamadas a funcin no modificarn accidentalmente nuestras variables
globales, aunque se llamen igual.
La siguiente figura ilustra la idea de que cada elemento del programa tiene un identificador
que lo hace accesible o visible desde un entorno o mbito diferente.
rea_tringulo
a
b
s
c
ngulo_alfa
a
b
s
c
men

s resultado
lado1 lado2 lado3

Cada funcin define un mbito local propio: su cuerpo. Los identificadores de las variables
locales solo son visibles en su mbito local. Por ejemplo, la variable opcin definida en la funcin
men solo es visible en el cuerpo de men. En este diagrama marcamos en tono gris la regin
en la que es visible esa variable:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

rea_tringulo
a
b
s
c
ngulo_alfa
a
b
s
c
men

s resultado
lado1 lado2 lado3

Fuera de la zona gris, tratar de acceder al valor de opcin se considera un error. Qu pasa
con las variables o parmetros de nombre idntico definidas en rea_tringulo y ngulo_alfa?
Considera, por ejemplo, el parmetro a o la variable s definida en rea_tringulo: solo es
accesible desde el cuerpo de rea_tringulo.
rea_tringulo
a
b
s
c
ngulo_alfa
a
b
s
c
men

s resultado
lado1 lado2 lado3

No hay confusin posible: cuando accedes al valor de a en el cuerpo de rea_tringulo,


accedes a su parmetro a. Lo mismo ocurre con la variable s o el parmetro a de ngulo_alfa:
si se usan en el cuerpo de la funcin, Python sabe que nos referimos a esas variables locales:
rea_tringulo
a
b
s
c
ngulo_alfa
a
b
s
c
men

s resultado
lado1 lado2 lado3

Hay un mbito global que incluye a aquellas lneas del programa que no forman parte del
cuerpo de una funcin. Los identificadores de las variables globales son visibles en el mbito
global y desde cualquier mbito local. Las variables resultado o lado1, por ejemplo, son accesibles
desde cualquier punto del programa (est dentro o fuera del cuerpo de una funcin). Podemos
representar as su zona de visibilidad, es decir, su mbito:
rea_tringulo
a
b
s
c
ngulo_alfa
a
b
s
c
men

s resultado
lado1 lado2 lado3

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Hay una excepcin a la regla de que las variables del mbito global sean accesibles desde
cualquier punto del programa: si el identificador de una variable (o funcin) definida en el mbito
global se usa para nombrar una variable local en una funcin, la variable (o funcin) global queda
oculta y no es accesible desde el cuerpo de la funcin. Por ejemplo, la variable local s definida
en la lnea 4 hace que la variable global s definida en la lnea 23 no sea visible en el cuerpo
de la funcin rea_tringulo. Su mbito se reduce a esta regin sombreada:
rea_tringulo
a
b
s
c
ngulo_alfa
a
b
s
c
men

s resultado
lado1 lado2 lado3

En el programa, la funcin ngulo_alfa presenta otro aspecto de inters: desde ella se llama
a la funcin rea_tringulo. El cuerpo de una funcin puede incluir llamadas a otras funciones.
Qu ocurre cuando efectuamos una llamada a ngulo_alfa? Supongamos que al ejecutar el
programa introducimos los valores 5, 4 y 3 para lado1, lado2 y lado3 y que escogemos la
opcin 2 del men. Al ejecutarse la lnea 28 ocurre lo siguiente:
Al evaluar la parte derecha de la asignacin de la lnea 28 se invoca la funcin ngulo_alfa
con los argumentos 5, 4 y 3, con lo que la ejecucin salta a la lnea 8 y a, b y c toman los
valores 5, 4 y 3, respectivamente. Python recuerda que al acabar de ejecutar la llamada,
debe seguir con la ejecucin de la lnea 28.
Se ejecuta la lnea 8 y, al evaluar la parte derecha de su asignacin, se invoca la
funcin rea_tringulo con los argumentos 5, 4 y 3 (que son los valores de a, b y
c). La ejecucin salta, pues, a la lnea 4 y Python recuerda que, cuando acabe de
ejecutar esta nueva llamada, regresar a la lnea 8.
En la lnea 4 la variable s local a rea_tringulo vale 6.0. Los parmetros a, b
y c son nuevas variables locales con valores 5, 4, y 3, respectivamente.
Se ejecuta la lnea 5 y se devuelve el resultado, que es 6.0.

Regresamos a la lnea 8, cuya ejecucin haba quedado suspendida a la espera


de conocer el resultado de la llamada a rea_tringulo. Como el resultado es 6.0,
se asigna dicho valor a la variable s local a ngulo_alfa. Se ejecuta la lnea 9 y se
devuelve el resultado de evaluar la expresin, que es 90.0.

Sigue la ejecucin en la lnea 28, que haba quedado en suspenso a la espera de conocer
el valor de la llamada a ngulo_alfa. Dicho valor se asigna a resultado.
Se ejecutan las lneas 30 y 31.

Podemos representar grficamente las distintas activaciones de funcin mediante el denominado rbol de llamadas. He aqu el rbol correspondiente al ltimo ejemplo:
programa principal

90.0

ngulo_alfa(5.0, 4.0, 3.0)


rea_tringulo
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

6.0

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Las llamadas se producen de arriba a abajo y siempre desde la funcin de la que parte
la flecha con trazo slido. La primera flecha parte del programa principal (fuera de cualquier
funcin). El valor devuelto por cada funcin aparece al lado de la correspondiente flecha de trazo
discontinuo.

301
Haz una traza de area_y_angulo py al solicitar el valor del ngulo opuesto al lado
de longitud 5 en un tringulo de lados con longitudes 5, 4 y 3.
1
2
3
4
5
6
7
8
9

10

302

Qu aparecer por pantalla al ejecutar el siguiente programa?

from math import sqrt

def rea_tringulo a b c
s
a
b
c
2
return sqrt s
s a
s
4
print rea_tringulo s 1
print s
print a

s b

s c

s 1

303
La funcin rea_tringulo que hemos definido puede provocar un error en tiempo
de ejecucin: si el argumento de la raz cuadrada calculada en su ltima lnea es un nmero
negativo, se producir un error de dominio. Haz que la funcin solo llame a sqrt si su argumento
es mayor o igual que cero. Si el argumento es un nmero negativo, la funcin debe devolver el
valor cero. Detecta tambin posibles problemas en ngulo_alfa y modifica la funcin para evitar
posibles errores al ejecutar el programa.

304
Vamos a adquirir una vivienda y para eso necesitaremos una hipoteca. La cuota
mensual m que hemos de pagar para amortizar una hipoteca de h euros a lo largo de n aos a
un inters compuesto del i por cien anual se calcula con la frmula:
m=

hr
,
1 (1 + r)12n

donde r = i/(100 12). Define una funcin que calcule la cuota (redondeada a dos decimales)
dados h, n e i. Utiliza cuantas variables locales consideres oportuno, pero al menos r debe
aparecer en la expresin cuyo valor se devuelve y antes debe calcularse y almacenarse en una
variable local.
Nota: puedes comprobar la validez de tu funcin sabiendo que hay que pagar la cantidad de
1.166,75 al mes para amortizar una hipoteca de 150.000 en 15 aos a un inters del 4,75 %
anual.

305
Disea una funcin que nos devuelva la cantidad de euros que habremos pagado
finalmente al banco si abrimos una hipoteca de h euros a un inters del i por cien en n aos.
Si te conviene, puedes utilizar la funcin que definiste en el ejercicio anterior.
Nota: con los datos del ejemplo anterior, habremos pagado un total de 210.015 .

306
Disea una funcin que nos diga qu cantidad de intereses (en euros) habremos
pagado finalmente al banco si abrimos una hipoteca de h euros a un inters del i por cien en n
aos. Si te conviene, puedes utilizar las funciones que definiste en los ejercicios anteriores.
Nota: con los datos del ejemplo anterior, habremos pagado un total de 210.015 150.000 =
60.015 en intereses.

307
Disea una funcin que nos diga qu tanto por cien del capital inicial deberemos
pagar en intereses al amortizar completamente la hipoteca. Si te conviene, puedes utilizar las
funciones que definiste en los ejercicios anteriores.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Nota: con los datos del ejemplo anterior, habremos pagado un inters total del 40,01 %
(60.015 es el 40,01 % de 150.000 ).

308
Disea un procedimiento que muestre por pantalla la cuota mensual que corresponde
pagar por una hipoteca para un capital de h euros al i % de inters anual durante 10, 15, 20 y 25
aos. (Si te conviene, rescata ahora las funciones que diseaste como solucin de los ejercicios
anteriores).

309
Disea un procedimiento que muestre por pantalla el capital total pagado al banco
por una hipoteca de h euros al i % de inters anual durante 10, 15, 20 y 25 aos. (Si te conviene,
rescata ahora las funciones que diseaste como solucin de los ejercicios anteriores).

Las variables locales tambin pueden contener valores secuenciales. Estudiemos un ejemplo
de funcin con una variable local de tipo secuencial: una funcin que recibe una lista y devuelve
otra cuyos elementos son los de la primera, pero sin repetir ninguno; es decir, si la funcin recibe
la lista 1 2 1 3 2 , devolver la lista 1 2 3 .
Empecemos por definir el cuerpo de la funcin:
1
2

def sin_repetidos lista

Cmo procederemos? Una buena idea consiste en disponer de una nueva lista auxiliar (una
variable local) inicialmente vaca en la que iremos insertando los elementos de la lista resultante.
Podemos recorrer la lista original elemento a elemento y preguntar a cada uno de ellos si ya
se encuentra en la lista auxiliar. Si la respuesta es negativa, lo aadiremos a la lista:
1
2
3
4
5
6

def sin_repetidos lista


resultado
for elemento in lista
if elemento not in resultado
resultado append elemento
return resultado

Fcil, no? La variable resultado es local, as que su tiempo de vida se limita al de la ejecucin
del cuerpo de la funcin cuando esta sea invocada. El contenido de resultado se devuelve con
la sentencia return, as que s ser accesible desde fuera. Aqu tienes un ejemplo de uso:
1
2
3
4
5
6
7
8
9

def sin_repetidos lista


resultado
for elemento in lista
if elemento not in resultado
resultado append elemento
return resultado
una_lista
sin_repetidos
print una_lista

310
Disea una funcin que reciba dos listas y devuelva los elementos comunes a ambas,
sin repetir ninguno (interseccin de conjuntos).
Ejemplo: si recibe las listas 1 2 1 y 2 3 2 4 , devolver la lista 2 .

311
Disea una funcin que reciba dos listas y devuelva los elementos que pertenecen a
una o a otra, pero sin repetir ninguno (unin de conjuntos).
Ejemplo: si recibe las listas 1 2 1 y 2 3 2 4 , devolver la lista 1 2 3 4 .
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

312
Disea una funcin que reciba dos listas y devuelva los elementos que pertenecen a
la primera pero no a la segunda, sin repetir ninguno (diferencia de conjuntos).
Ejemplo: si recibe las listas 1 2 1 y 2 3 2 4 , devolver la lista 1 .

313
Disea una funcin que, dada una lista de nmeros, devuelva otra lista que solo
incluya sus nmeros impares.

314
Disea una funcin que, dada una lista de nombres y una letra, devuelva una lista
con todos los nombres que empiezan por dicha letra.

315
Disea una funcin que, dada una lista de nmeros, devuelva otra lista con solo
aquellos nmeros de la primera que son primos.

316
Disea una funcin que, dada una lista de nmeros, devuelva una lista con todos los
pares de nmeros que podemos formar con uno de la primera lista y otro de la segunda. Por
ejemplo, si se suministran las listas 1 3 5 y 2 5 , la lista resultante es
1 2
1 5
3 2
3 5
5 2
5 5 .
317
Disea una funcin que, dada una lista de nmeros, devuelva una lista con todos los
pares de nmeros amigos que podemos formar con uno de la primera lista y otro de la segunda.

6.4.

El mecanismo de las llamadas a funcin

6.4.1.

La pila de llamadas a funcin y el paso de parmetros

Hemos visto que desde una funcin podemos llamar a otra funcin. Desde esta ltima funcin
podramos llamar a otra, y desde esta an a otra. . . Cada vez que se produce una llamada, la
ejecucin del programa principal o de la funcin actual queda suspendida a la espera de
que finalice la llamada realizada y prosigue cuando esta finaliza. Cmo recuerda Python qu
funciones estn suspendidas y en qu orden deben reanudarse?
Por otra parte, hemos visto que si una variable local a una funcin tiene el mismo nombre
que una variable global, durante la ejecucin de la funcin la variable local oculta a la global y
su valor es inaccesible. Cmo es posible que al finalizar la ejecucin de una funcin se restaure
el valor original? Dnde se haba almacenado este mientras la variable era invisible?
Python utiliza internamente una estructura especial de memoria para recordar la informacin
asociada a cada invocacin de funcin: la pila de llamadas a funcin. Una pila es una serie de
elementos a la que solo podemos aadir y eliminar componentes por uno de sus dos extremos:
el que denominamos la cima.
Un montn de platos, por ejemplo, es una pila: solo puedes aadir un plato ponindolo encima
de la pila (apilar) y solo puedes quitar el plato que est encima (desapilar). Aqu tienes una
representacin grfica de una pila con cuatro elementos (cada uno de ellos es un nmero entero).
4
3
2
1

Solo podemos aadir nuevos elementos (apilar) por el extremo superior:


Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Y solo podemos eliminar el elemento de la cima (desapilar):


5
4

Cada activacin de una funcin apila un nuevo componente en la pila de llamadas a funcin.
Dicho componente, que recibe el nombre de trama de activacin, es una zona de memoria en la
que Python dispondr espacio para los punteros asociados a parmetros, variables locales y otra
informacin que se ha de recordar, como el punto exacto desde el que se efectu la llamada a la
funcin. Cuando iniciamos la ejecucin de un programa, Python reserva una trama especial para
las variables globales, as que empezamos con un elemento en la pila. Estudiemos un ejemplo:
una ejecucin particular del programa area_y_angulo py que reproducimos aqu:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

from math import sqrt

asin

def rea_tringulo a b c
s
a
b
c
2
return sqrt s
s a

pi

s b

s c

def ngulo_alfa a b c
s
rea_tringulo a b c
return 180
pi
asin 2
s

b c

def men
opcin
0
while opcin
1 and opcin
print
print
opcin
int input
return opcin
lado1
lado2
lado3
s

if s

else

float input
float input
float input

men

1
resultado
resultado

rea_tringulo lado1
ngulo_alfa lado1

lado2

lado2

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

lado3

lado3

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

30
31

print
print

s
resultado

Aqu tienes un pantallazo con el resultado de dicha ejecucin:

Cuando el programa arranca, Python prepara en la pila el espacio necesario para las variables
globales:
lado3
lado2
lado1
s

Programa principal

resultado

El usuario introduce a continuacin el valor de lado1, lado2 y lado3. La memoria queda as:
Programa principal

lado3
lado2
lado1
s

resultado

3
4
5

Se produce entonces la llamada a la funcin men. Python crea una trama de activacin para
la llamada y la dispone en la cima de la pila. En dicha trama se almacena el valor de opcin y
el punto desde el que se efectu la llamada a men. Aqu tienes una representacin de la pila
cuando el usuario acaba de introducir por teclado la opcin seleccionada:
men
Programa principal

opcin

llamada desde lnea 23

lado3
lado2
lado1
s

resultado

2
3
4
5

Qu ocurre cuando finaliza la ejecucin de la funcin men? Ya no hace falta la trama de


activacin, as que se desapila, es decir, se elimina. Momentneamente, no obstante, se mantiene
una referencia al objeto devuelto, en este caso, el contenido de la variable opcin. Python recuerda
en qu lnea del programa principal debe continuar (lnea 23) porque se haba memorizado en
la trama de activacin. La lnea 23 dice:
1

men

as que la referencia devuelta por men con la sentencia return es apuntada ahora por la
variable s:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

return
Programa principal

lado3
lado2
lado1
s

resultado

2
3
4
5

Y ahora que ha desaparecido completamente la trama de activacin de men, podemos reorganizar grficamente los objetos apuntados por cada variable:
Programa principal

lado3
lado2
lado1
s

resultado

3
4
5
2

La ejecucin prosigue y, en la lnea 28, se produce una llamada a la funcin ngulo_alfa. Se


crea entonces una nueva trama de activacin en la cima de la pila con espacio para los punteros
de los tres parmetros y el de la variable local s. A continuacin, cada parmetro apunta al
correspondiente valor: el parmetro a apunta adonde apunta lado1, el parmetro b adonde lado2
y el parmetro c adonde lado3. Esta accin se denomina paso de parmetros.
ngulo_alfa
Programa principal

s
c

b
a

llamada desde lnea 28

lado3
lado2
lado1
s

resultado

3
4
5
2

Desde el cuerpo de la funcin ngulo_alfa se llama a la funcin rea_tringulo, as que


se crea una nueva trama de activacin. Fjate en que los identificadores de los parmetros y
las variables locales de las dos tramas superiores tienen los mismos nombres, pero residen en
espacios de memoria diferentes. En esta nueva imagen puedes ver el estado de la pila en el
instante preciso en que se efecta la llamada a rea_tringulo y se ha producido el paso de
parmetros:
rea_tringulo

ngulo_alfa
Programa principal

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

s
c

b
a

llamada desde lnea 8

s
c

b
a

llamada desde lnea 28

lado3
lado2
lado1
s

resultado

3
4
5
2

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Como puedes comprobar, los parmetros a, b y c de rea_tringulo apuntan al mismo lugar


que los parmetros del mismo nombre de ngulo_alfa.
Cuando rea_tringulo ejecuta su primera lnea, la variable local s recibe el valor 6.0:
rea_tringulo

ngulo_alfa
Programa principal

s
c

6.0

b
a

llamada desde lnea 8

s
c

b
a

llamada desde lnea 28

lado3
lado2
lado1
s

resultado

3
4
5
2

La ejecucin de rea_tringulo finaliza devolviendo el valor del rea, que resulta ser 6.0. La
variable s local a ngulo_alfa apunta a dicho valor, pues hay una asignacin al resultado de la
funcin en la lnea 8:
rea_tringulo

ngulo_alfa
Programa principal

return

llamada desde lnea 8

s
c

b
a

llamada desde lnea 28

lado3
lado2
lado1
s

resultado

Nuevamente podemos simplificar la figura as:

ngulo_alfa
Programa principal

s
c

3
4
5
2

6.0

b
a

llamada desde lnea 28

lado3
lado2
lado1
s

6.0

resultado

3
4
5
2

Y, ahora, una vez finaliza la ejecucin de ngulo_alfa, el valor devuelto (90.0) se almacena
en la variable global resultado:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

90.0

return
lado3
lado2
lado1
s

Programa principal

El estado final de la pila es, pues, este:


Programa principal

resultado

lado3
lado2
lado1
s

resultado

3
4
5
2

3
4
5
2
90.0

Observa que la variable s de la trama de activacin del programa principal siempre ha


valido 2, aunque las variables locales del mismo nombre han almacenado diferentes valores a lo
largo de la ejecucin del programa.

6.4.2.

Paso del resultado de expresiones como argumentos

Hemos visto que el paso de parmetros comporta que el parmetro apunte a cierto lugar
de la memoria. Cuando el argumento es una variable, es fcil entender qu ocurre: tanto el
parmetro como la variable apuntan al mismo lugar. Pero, qu ocurre si pasamos una expresin
como argumento? Veamos un ejemplo:
1
2
3
4
5
6
7

def incrementa p
p
p
1
return p

a
1
a
incrementa 2 2
print
a

Observa que no hemos pasado a incrementa una variable, sino el valor 4 (resultado de evaluar
la expresin 2 2).
He aqu el estado de la memoria en el preciso instante en el que se produce el paso de
parmetros:
incrementa

Programa principal

llamada desde lnea 6

4
1

El parmetro p apunta a una nueva zona de memoria que contiene el resultado de evaluar
la expresin.
La operacin de incremento de la lnea 2 hace que p pase a valer 5:
incrementa

Programa principal

y ese es el valor devuelto en la lnea 3.


Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

llamada desde lnea 6

5
1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Programa principal

return
a

As pues, la variable global a recibe el valor devuelto y es este el que se muestra por pantalla:

6.4.3.

Ms sobre el paso de parmetros

Hemos visto que el paso de parmetros comporta que cada parmetro apunte a un lugar de
la memoria y que este puede estar ya apuntado por una variable o parmetro perteneciente al
mbito desde el que se produce la llamada. Qu ocurre si el parmetro es modificado dentro
de la funcin? Se modificar igualmente la variable o parmetro del mbito desde el que se
produce la llamada? Depende. Estudiemos unos cuantos ejemplos.
Para empezar, uno bastante sencillo:
1
2
3
4
5
6
7
8
9

def incrementa p
p
p
1
return p
a
b

print
print

1
incrementa a
a
b

Veamos qu sale por pantalla al ejecutarlo:

Puede que esperaras que tanto a como b tuvieran el mismo valor al final: a fin de cuentas la
llamada a incrementa en la lnea 6 hizo que el parmetro p apuntara al mismo lugar que a y esa
funcin incrementa el valor de p en una unidad (lnea 2). No debera, pues, haberse modificado
el valor de a? No.
Veamos qu ocurre paso a paso. Inicialmente tenemos en la pila la reserva de memoria para
las variables a y b. Tras ejecutar la lnea 5, a tiene por valor el entero 1:
Programa principal

b
a

incrementa

llamada desde lnea 6

Cuando llamamos a incrementa el parmetro p recibe una referencia al valor apuntado por
a. As pues, tanto a como p apuntan al mismo lugar y valen 1:
p

Programa principal

b
a

incrementa

llamada desde lnea 6

El resultado de ejecutar la lnea 2 hace que p apunte a una nueva zona de memoria en la
que se guarda el valor 2!
Programa principal

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

b
a

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Por qu? Recuerda cmo procede Python ante una asignacin:

en primer lugar se evala la expresin a mano derecha del igual,

y a continuacin se hace que la parte izquierda del igual apunte al resultado.

La evaluacin de una expresin proporciona una referencia a la zona de memoria que alberga el
resultado. As pues, la asignacin tiene un efecto sobre la referencia de p, no sobre el contenido de
la zona de memoria apuntada por p. Cuando Python ha evaluado la parte derecha de la asignacin
de la lnea 2, ha sumado al valor 1 apuntado por p el valor 1 que aparece explcitamente. El
resultado es 2, as que Python ha reservado una nueva celda de memoria con dicho valor.
Finalmente, se ha asignado a p el resultado de la expresin, es decir, se ha hecho que p apunte
a la celda de memoria con el resultado.
Sigamos con la ejecucin de la llamada a la funcin. Al finalizar esta, la referencia de p se
devuelve y, en la lnea 6, se asigna a b.
return

Programa principal

b
a

Programa principal

b
a

2
1

Resultado: b vale lo que vala p al final de la llamada y a no ve modificado su valor:

1
2
3
4
5
6
7
8
9

318

2
1

Qu aparecer por pantalla al ejecutar este programa?

def incrementa a
a
a
1
return a
a
b

print
print

1
incrementa a
a
b

Hazte un dibujo del estado de la pila de llamadas paso a paso para entender bien qu est
pasando al ejecutar cada sentencia.
1
2
3
4
5
6
7
8
9

10
11
12

Y ahora, la sorpresa:

def modifica a b
a append 4
b
b
4
return b
lista1
lista2
lista3

1 2 3
1 2 3

modifica lista1

print lista1
print lista2

lista2

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

13

print lista3

Ejecutemos el programa:
Qu ha ocurrido? La lista que hemos proporcionado como primer argumento se ha modificado
al ejecutarse la funcin y la que sirvi de segundo argumento no.
Ya deberas tener suficientes datos para averiguar qu ha ocurrido. No obstante, nos detendremos brevemente a explicarlo. Veamos en qu estado est la memoria en el momento en el
que se produce el paso de parmetros en la llamada a modifica:
modifica

llamada desde lnea 9

lista3

Programa principal

lista2

lista1

3
3

Qu ocurre cuando se ejecuta la lnea 2? Que la lista apuntada por a crece por el final (con
append) con un nuevo elemento de valor 4:
modifica

llamada desde lnea 9

lista3

Programa principal

lista2

lista1

2
2

3
3

Como esa lista est apuntada tanto por el parmetro a como por la variable global lista1,
ambos sufren el cambio y ven modificado su valor. Pasemos ahora a la lnea 3: una asignacin.
Como siempre, Python empieza por evaluar la parte derecha de la asignacin, donde se indica
que se debe crear una nueva lista con capacidad para cuatro elementos (los valores 1, 2 y 3 que
provienen de b y el valor 4 que aporta la lista 4 ). Una vez creada la nueva lista, se procede
a que la variable de la parte izquierda apunte a ella:
modifica

llamada desde lnea 9

Programa principal

lista3

lista2

lista1

2
2

3
3

Cuando finaliza la ejecucin de modifica, lista3 pasa a apuntar a la lista devuelta por la
funcin, es decir, a la lista que hasta ahora apuntaba b:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

return
Programa principal

Y aqu tenemos el resultado final:


Programa principal

Recuerda, pues, que:

lista3

lista2

lista1

lista3

lista2

lista1

2
2
2

2
2
2

3
3
3

3
3
3

La asignacin puede comportar un cambio del lugar de memoria al que apunta una variable.
Si un parmetro modifica su valor mediante una asignacin, (probablemente) obtendr una
nueva zona de memoria y perder toda relacin con el argumento del que tom valor al
efectuar el paso de parmetros.

Operaciones como append, del o la asignacin a elementos indexados de listas modifican


la propia lista, por lo que los cambios afectan tanto al parmetro como al argumento.

Con las cadenas ocurre algo similar a lo estudiado con las listas, solo que las cadenas son inmutables y no pueden sufrir cambio alguno mediante operaciones como append, del o asignacin
directa a elementos de la cadena. De hecho, ninguna de esas operaciones es vlida sobre una
cadena.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16

1
2
3

319

Qu mostrar por pantalla el siguiente programa al ejecutarse?

def modifica a b
for elemento in b
a append elemento
b
b
4
a 1
100
del b 0
return b
lista1
lista2

1 2 3
1 2 3

lista3

modifica lista1

320

Qu muestra por pantalla este programa al ser ejecutado?

print lista1
print lista2
print lista3

lista2

def modifica_parmetros x
x
1
y 0
1

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4
5
6
7
8
9

10

1
2
3
4
5
6
7
8
9

10
11

a
0
b
0 1 2
modifica_parmetros a
print a
print b

321

Qu muestra por pantalla este programa al ser ejecutado?

def modifica_parmetros x
x
1
y append 3
y
y
4
y 0
10
a
0
b
0 1 2
modifica_parmetros a
print a
print b

322
Utiliza las funciones desarrolladas en el ejercicio 295 y disea nuevas funciones
para construir un programa que presente el siguiente men y permita ejecutar las acciones
correspondientes a cada opcin:

Ahora que sabemos que dentro de una funcin podemos modificar listas, vamos a disear una
funcin que invierta una lista. Ojo!: no una funcin que, dada una lista, devuelva otra que sea
la inversa de la primera, sino un procedimiento (recuerda: una funcin que no devuelve nada)
que, dada una lista, la modifique invirtindola.
El aspecto de una primera versin podra ser este:
E
1
2
3

E
1
2
3
4
5
6
7
8
9

def invierte lista


for i in range len lista
intercambiar los elementos lista i

y lista len lista

1 i

Intercambiaremos los dos elementos usando una variable auxiliar:

def invierte lista


for i in range len lista
c
lista i
lista i
lista len lista 1 i
lista len lista 1 i
c
a
1 2
invierte a
print a

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

No funciona. Parece que no la haya modificado. En realidad s que lo ha hecho, pero mal.
Estudiemos paso a paso qu ha ocurrido:
1) Al llamar a la funcin, el parmetro lista apunta (hace referencia) a la misma zona de
memoria que la variable a.

2) El bucle que empieza en la lnea 2 va de 0 a 3 (pues la longitud de lista es 4). La variable


local i tomar los valores 0, 1, 2 y 3.
1) Cuando i vale 0, el mtodo considera los elementos lista 0 y lista 3 :
0

La variable local c toma el valor 1 (que es el contenido de lista 0 ), a continuacin lista 0


toma el valor de lista 3 y, finalmente, lista 3 toma el valor de c. El resultado es que
se intercambian los elementos lista 0 y lista 3 :
0

2) Ahora i vale 1, as que se consideran los elementos lista 1 y lista 2 :


0

Los dos elementos se intercambian y la lista queda as:


0

3) Ahora i vale 2, as que se consideran los elementos lista 2 y lista 1 :


0

Tras el intercambio, la lista pasa a ser:

4) Y, finalmente, i vale 3.

Se intercambian los valores de las celdas lista 3 y lista 0 :


0

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Fjate en que al final de la segunda iteracin del bucle la lista estaba correctamente invertida.
Lo que ha ocurrido es que hemos seguido iterando y hemos vuelto a invertir una lista que ya
estaba invertida, dejndola como estaba al principio! Ya est claro cmo actuar: iterando la mitad
de las veces. Vamos all:
1
2
3
4
5
6
7
8
9

def invierte lista


for i in range len lista
2
c
lista i
lista i
lista len lista 1 i
lista len lista 1 i
c
a
1 2
invierte a
print a

Ahora s. Si ejecutamos el programa obtenemos:

323
Qu ocurre con el elemento central de la lista cuando la lista tiene un nmero impar
de elementos? Nuestra funcin invierte correctamente la lista?
1
2
3
4
5

1
2
3
4
5
6
7

1
2
3
4
5
6
7
8
9

10
11
12

324

Un aprendiz sugiere esta otra solucin. Funciona?

def invierte lista


for i in range len lista
c
lista i
lista i
lista i 1
lista i 1
c

325

Qu muestra por pantalla este programa al ser ejecutado?

def abs_lista lista


for i in range len lista
lista i
abs lista i
milista
1
1
abs_lista milista
print milista

326

Qu mostrar por pantalla el siguiente programa al ejecutarse?

def intento_de_intercambio a
aux
a
a
b
b
aux
lista1
lista2

1 2
3 4

intento_de_intercambio lista1
print lista1
print lista2

lista2

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

327
Disea un procedimiento que, dada una lista de nmeros, la modifique para que solo
sobrevivan a la llamada aquellos nmeros que son perfectos.

328
Disea una funcin duplica que reciba una lista de nmeros y la modifique duplicando
el valor de cada uno de sus elementos. (Ejemplo: la lista 1 2 3 se convertir en la lista
2 4 6 ).

329
Disea una funcin duplica_copia que reciba una lista de nmeros y devuelva otra
lista en la que cada elemento sea el doble del que tiene el mismo ndice en la lista original. La
lista original no debe sufrir ninguna modificacin tras la llamada a duplica_copia.

330
Disea una funcin que reciba una lista y devuelva otra lista cuyo contenido sea el
resultado de concatenar la lista original consigo misma. La lista original no debe modificarse.

331
Disea una funcin que reciba una lista y devuelva otra lista cuyo contenido sea la
lista original, pero con sus componentes en orden inverso. La lista original no debe modificarse.

332
Disea una funcin que reciba una lista y devuelva una lista cuyo contenido sea
la lista original concatenada con una versin invertida de ella misma. La lista original no debe
modificarse.

333
mayor.

Disea un procedimiento que reciba una lista y ordene sus elementos de menor a

334
Disea una funcin que reciba una lista y devuelva una copia de la lista con sus
elementos ordenados de menor a mayor. La lista original no debe modificarse.

335
Disea una funcin que reciba una matriz y, si es cuadrada (es decir, tiene igual
nmero de filas que de columnas), devuelva la suma de todos los componentes dispuestos en la
diagonal principal (es decir, todos los elementos de la forma Ai,i ). Si la matriz no es cuadrada,
la funcin devolver None.

336
Guardamos en una matriz de m n elementos la calificacin obtenida por m estudiantes (a los que conocemos por su nmero de lista) en la evaluacin de n ejercicios entregados
semanalmente (cuando un ejercicio no se ha entregado, la calificacin es 1).
Disea funciones y procedimientos que efecten los siguiente clculos:
Dado el nmero de un alumno, devolver el nmero de ejercicios entregados.

Dado el nmero de un alumno, devolver la media sobre los ejercicios entregados.

Dado el nmero de un alumno, devolver la media sobre los ejercicios entregados si los
entreg todos; en caso contrario, la media es 0.

Devolver el nmero de todos los alumnos que han entregado todos los ejercicios y tienen
una media superior a 3,5 puntos.
Dado el nmero de un ejercicio, devolver el nmero de estudiantes que lo han presentado.
Dado el nmero de un ejercicio, devolver la nota media obtenida por los estudiantes que
lo presentaron.
Dado el nmero de un ejercicio, devolver la nota ms alta obtenida.

Dado el nmero de un ejercicio, devolver la nota ms baja obtenida.

Devolver el nmero de abandonos en funcin de la semana. Consideramos que un alumno


abandon en la semana s si no ha entregado ningn ejercicio desde entonces. Este procedimiento mostrar en pantalla el nmero de abandonos para cada semana (si un alumno
no ha entregado nunca ningn ejercicio, abandon en la semana cero).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6.4.4.

Acceso a variables globales desde funciones

Por lo dicho hasta ahora podras pensar que en el cuerpo de una funcin solo pueden
utilizarse variables locales. No es cierto. Dentro de una funcin tambin puedes consultar y
modificar variables globales. Eso s, debers avisar a Python de que una variable usada en el
cuerpo de una funcin es global antes de usarla. Lo veremos con un ejemplo.
Vamos a disear un programa que gestiona una de las funciones de un cajero automtico
que puede entregar cantidades que son mltiplo de 10 . En cada momento, el cajero tiene
un nmero determinado de billetes de 50, 20 y 10 . Utilizaremos una variable para cada tipo
de billete y en ella indicaremos cuntos billetes de ese tipo nos quedan en el cajero. Cuando
un cliente pida sacar una cantidad determinada de dinero, mostraremos por pantalla cuntos
billetes de cada tipo le damos. Intentaremos darle siempre la menor cantidad de billetes posible.
Si no es posible darle el dinero (porque no tenemos suficiente dinero en el cajero o porque
la cantidad solicitada no puede darse con una combinacin vlida de los billetes disponibles)
informaremos al usuario.
Inicialmente supondremos que el cajero est cargado con 100 billetes de cada tipo:
1
2
3

carga50
carga20
carga10

100
100
100

carga50
carga20
carga10

100
100
100

Disearemos ahora una funcin que, ante una peticin de dinero, muestre por pantalla los
billetes de cada tipo que se entregan. La funcin devolver una lista con el nmero de billetes
de 50, 20 y 10 si se pudo dar el dinero, y la lista 0 0 0 en caso contrario. Intentmoslo.
E
1
2
3
4
5
6
7
8
9

10
11

def sacar_dinero cantidad


de50
cantidad
50
cantidad
cantidad
50
de20
cantidad
20
cantidad
cantidad
20
de10
cantidad
10
return de50 de20 de10

sacar_dinero

cantidad

billetes de 10
billetes de 20
billetes de 50

Entiendes las frmulas utilizadas para calcular el nmero de billetes de cada tipo? Estdialas con calma antes de seguir.
En principio, ya est. Bueno, no; hemos de restar los billetes que le damos al usuario de las
variables carga50, carga20 y carga10, pues el cajero ya no los tiene disponibles para futuras
extracciones de dinero:
E
1
2
3
4
5
6

carga50
carga20
carga10

100
100
100

def sacar_dinero cantidad


de50
cantidad
50

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7
8
9

10
11
12
13
14

E
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

cantidad
cantidad
50
de20
cantidad
20
cantidad
cantidad
20
de10
cantidad
10
carga50
carga50
de50
carga20
carga20
de20
carga10
carga10
de10
return de50 de20 de10

Probemos el programa aadiendo, momentneamente, un programa principal:

carga50
carga20
carga10

100
100
100

def sacar_dinero cantidad


de50
cantidad
50
cantidad
cantidad
50
de20
cantidad
20
cantidad
cantidad
20
de10
cantidad
10
carga50
carga50
de50
carga20
carga20
de20
carga10
carga10
de10
return de50 de20 de10
c
int input
print sacar_dinero c

Qu ocurrir con el acceso a carga50, carga20 y carga10? Puede que Python las tome por
variables locales, en cuyo caso, no habremos conseguido el objetivo de actualizar la cantidad de
billetes disponibles de cada tipo. Lo que ocurre es peor an: al ejecutar el programa obtenemos
un error.

El error es del tipo UnboundLocalError (que podemos traducir por error de variable local
no ligada) y nos indica que hubo un problema al tratar de acceder a carga50, pues es una
variable local que no tiene valor asignado previamente. Pero, carga50 debera ser una variable
global, no local, y adems s se le asign un valor: en la lnea 1 asignamos a carga50 el valor
100! Por qu se confunde? Python utiliza una regla simple para decidir si una variable usada
en una funcin es local o global: si se le asigna un valor, es local; si no, es global. Las variables
carga50, carga20 y carga10 aparecen en la parte izquierda de una asignacin, as que Python
supone que son variables locales. Y si son locales, no estn inicializadas cuando se evala la
parte derecha de la asignacin. Hay una forma de evitar que Python se equivoque en situaciones
como esta: declarar explcitamente que esas variables son globales. Fjate en la lnea 6:
E
1
2
3
4
5
6
7

carga50
carga20
carga10

100
100
100

def sacar_dinero cantidad


global carga50 carga20
de50
cantidad
50

carga10

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

8
9

10
11
12
13
14
15
16
17
18

cantidad
cantidad
50
de20
cantidad
20
cantidad
cantidad
20
de10
cantidad
10
carga50
carga50
de50
carga20
carga20
de20
carga10
carga10
de10
return de50 de20 de10

c
int input
print sacar_dinero c

Perfecto! Hagamos una prueba ms:


No ves nada raro? La funcin ha dicho que nos han de dar 140 billetes de 50 , cuando solo
hay 100! Hemos de refinar la funcin y hacer que nos d la cantidad solicitada solo cuando
dispone de suficiente efectivo:
E
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21

carga50
carga20
carga10

100
100
100

def sacar_dinero cantidad


global carga50 carga20 carga10
if cantidad
50
carga50
20
de50
cantidad
50
cantidad
cantidad
50
de20
cantidad
20
cantidad
cantidad
20
de10
cantidad
10
carga50
carga50
de50
carga20
carga20
de20
carga10
carga10
de10
return de50 de20 de10
else
return 0 0 0

carga20

10

carga10

c
int input
print sacar_dinero c

La lnea 7 se encarga de averiguar si hay suficiente dinero en el cajero. Si no lo hay, la


funcin finaliza inmediatamente devolviendo la lista 0 0 0 . Funcionar ahora?
No! Sigue funcionando mal. Claro!, hay 50 100 + 20 100 + 10 100 = 8000 en el
cajero y hemos pedido 7000 . Lo que deberamos controlar no (solo) es que haya suficiente
dinero, sino que haya suficiente cantidad de billetes de cada tipo:
1
2
3
4
5

carga50
carga20
carga10

100
100
100

def sacar_dinero cantidad

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

global carga50 carga20 carga10


if cantidad
50
carga50
20
carga20
10
carga10
de50
cantidad
50
cantidad
cantidad
50
if de50
carga50
Si no hay suficientes billetes de 50
cantidad
cantidad
de50
carga50
50
de50
carga50
de20
cantidad
20
cantidad
cantidad
20
if de20
carga20
y no hay suficientes billetes de 20
cantidad
cantidad
de20
carga20
20
de20
carga20
de10
cantidad
10
cantidad
cantidad
10
if de10
carga10
y no hay suficientes billetes de 10
cantidad
cantidad
de10
carga10
10
de10
carga10
Si todo ha ido bien, la cantidad que resta por entregar es nula:
if cantidad
0
As que hacemos efectiva la extraccin
carga50
carga50
de50
carga20
carga20
de20
carga10
carga10
de10
return de50 de20 de10
else
Y si no, devolvemos la lista con tres ceros:
return 0 0 0
else
return 0 0 0

c
int input
print sacar_dinero c

Bueno, parece que ya tenemos la funcin completa. Hagamos algunas pruebas:

Ahora s!

337
Hay dos ocasiones en las que se devuelve la lista 0 0 0 . Puedes modificar el
programa para que solo se devuelva esa lista explcita desde un punto del programa?

Como ya hemos diseado y probado la funcin, hagamos un ltimo esfuerzo y acabemos el


programa. Eliminamos las lneas de prueba (las dos ltimas) y aadimos el siguiente cdigo:
1
2
3
4
5
6
7
8
9

10
11

carga50
carga20
carga10

100
100
100

def sacar_dinero cantidad


global carga50 carga20 carga10
if cantidad
50
carga50
20
carga20
10
carga10
de50
cantidad
50
cantidad
cantidad
50
if de50
carga50
Si no hay suficientes billetes de 50
cantidad
cantidad
de50
carga50
50

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

else

de50
carga50
de20
cantidad
20
cantidad
cantidad
20
if de20
carga20
y no hay suficientes billetes de 20
cantidad
cantidad
de20
carga20
20
de20
carga20
de10
cantidad
10
cantidad
cantidad
10
if de10
carga10
y no hay suficientes billetes de 10
cantidad
cantidad
de10
carga10
10
de10
carga10
Si todo ha ido bien, la cantidad que resta por entregar es nula:
if cantidad
0
As que hacemos efectiva la extraccin
carga50
carga50
de50
carga20
carga20
de20
carga10
carga10
de10
return de50 de20 de10
else
Y si no, devolvemos la lista con tres ceros:
return 0 0 0
return

Programa principal
while 50 carga50
20 carga20
10 carga10
0
peticin
int input
de50 de20 de10
sacar_dinero peticin
if de50 de20 de10
0 0 0
if de50
0
print
de50
if de20
0
print
de20
if de10
0
print
de10
print
else
print
print

Usemos esta versin final del programa:

Acabaremos este apartado con una reflexin. Ten en cuenta que modificar variables globales
desde una funcin no es una prctica de programacin recomendable. La experiencia dice que
solo en contadas ocasiones est justificado que una funcin modifique variables globales. Se
dice que modificar variables globales desde una funcin es un efecto secundario de la llamada
a la funcin. Si cada funcin de un programa largo modificara libremente el valor de variables
globables, tu programa sera bastante ilegible y, por tanto, difcil de ampliar o corregir en el
futuro.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Se supone que un cajero de verdad debe entregar dinero

El programa del cajero automtico no parece muy til: se limita a imprimir por pantalla el nmero
de billetes de cada tipo que nos ha de entregar. Se supone que un cajero de verdad debe entregar
dinero y no limitarse a mostrar mensajes por pantalla.
Los cajeros automticos estn gobernados por un computador. Las acciones del cajero pueden
controlarse por medio de funciones especiales. Estas funciones acceden a puertos de entrada/salida
del ordenador que se comunican con los perifricos adecuados. El aparato que entrega billetes no es
ms que eso, un perifrico ms.
Lo lgico sera disponer de un mdulo, digamos dispensador_de_billetes, que nos diera acceso a
las funciones que controlan el perifrico. Una funcin podra, por ejemplo, entregar al usuario tantos
billetes de cierto tipo como se indicara. Si dicha funcin se llamara entrega, en lugar de una sentencia
como print
de50 , realizaramos la llamada entrega de50 50 .

6.5.

Un ejemplo: Memorin

Ya es hora de hacer algo interesante con todo lo que hemos aprendido. Vamos a construir un
sencillo juego solitario, Memorin, con el que aprenderemos, entre otras cosas, a manejar el ratn.
Memorin se juega sobre un tablero de 4 filas y 6 columnas. Cada celda del tablero contiene
un smbolo (una letra), pero no es visible porque est tapado por una baldosa. De cada smbolo
hay dos ejemplares (dos a, dos b, etc.) y hemos de emparejarlos. Una jugada consiste en
levantar dos baldosas para ver las letras que hay bajo ellas. Primero se levanta una pulsando
en la baldosa, con lo que se destapa el smbolo que oculta, y despus se destapa la otra y se
muestra brevemente su smbolo oculto correspondiente. Si las letras descubiertas son iguales,
hemos conseguido un emparejamiento y las baldosas se retiran del tablero, dejando las letras
definitivamente al descubierto. Si, por el contrario, las letras son diferentes, se tapan de nuevo.
Encontrar sus respectivas parejas depender entonces de la memoria del jugador. El objetivo es
emparejar todas las letras en el menor nmero de jugadas.
Esta figura te muestra una partida de Memorin ya empezada:

Por dnde empezamos a escribir el programa? Pensemos en qu informacin necesitaremos. Por


una parte, necesitaremos una matriz con 46 celdas para almacenar las letras. Por otra parte, otra
matriz paralela que nos diga si la casilla ya est descubierta o permanece cerrada. Nos vendr
bien disponer de una rutina que construya una matriz con la dimensin que especifiquemos, pues
la usaremos tanto para construir la matriz de letras como la matriz de baldosas:
1
2
3
4
5

def crea_matriz filas columnas


matriz
for i in range filas
matriz append None
return matriz

columnas

En el programa principal usaremos esta rutina as:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

2
3
4
5
6

Programa principal
filas
4
columnas
6
smbolo
crea_matriz filas columnas
tablero
crea_matriz filas columnas

Para inicializar el tablero con todas las casillas cerradas bastar con asignar un valor que
represente ese estado en todas las celdas de su matriz. En principio parece que solo haya dos
estados posibles, pero si lo piensas bien, vers que en realidad hay tres estados diferentes: la
celda est tapada, la celda est destapada. . . y la celda est temporalmente destapada. El tercer
estado corresponde al momento en que estamos viendo el smbolo que esconde una baldosa por
haber hecho clic sobre ella, pero sin haber logrado an un emparejamiento con ella. Usaremos
tres valores para representar estos tres estados. En aras de la legibilidad del programa, cada
valor se almacenar en una variable con un identificador explicativo:
1
2
3
4
5
6
7
8

CeldaCerrada
0
CeldaAbierta
1
CeldaTemporalmenteAbierta

def inicializa_tablero tablero


for i in range filas
for j in range columnas
tablero i j
CeldaCerrada

Nuestro primer problema importante es inicializar la matriz de letras al azar. Cmo podemos
resolverlo? Te sugerimos que consideres estas estrategias:

Como vamos a ubicar 12 letras diferentes (dos ejemplares de cada), un bucle va recorriendo
los caracteres de la cadena
. Para cada letra, elegimos dos pares de
va
coordenadas al azar (ahora veremos cmo). Imagina que decidimos que la letra
a las posiciones (i, j) y (i , j  ), donde i e i son nmeros de fila y j y j  son nmeros de
columna. Hemos de asegurarnos de que las casillas (i, j) e (i , j  ) son diferentes y no estn
ya ocupadas con otras letras. (Ten en cuenta que hemos generado esos pares de nmeros
al azar, as que pueden caer en cualquier sitio y este no tiene por qu estar libre). Mientras
generemos un par de coordenadas que corresponden a una casilla ocupada, repetiremos
la tirada.
1
2
3
4
5
6
7
8
9

10
11

from random import randrange

def rellena_smbolos smbolo


Primera versin.
for carcter in
for ejemplar in range 2
ocupado
True
while ocupado
i j
randrange len smbolo
if smbolo i j
None
ocupado
False
smbolo i j
carcter

randrange len smbolo 0

Para generar el nmero de fila y columna usamos randrange, que devuelve un valor aleatorio y entero mayor o igual que 0 y menor que el valor del argumento que se le proporciona.
Resulta til conocer bien las libreras estndar de Python.
En principio, no ha sido demasiado complicado disear esta funcin, pero el mtodo por el
que elegimos casillas al azar presenta un serio problema: como genera coordenadas al azar
hasta dar con una libre, qu ocurrir, probablemente, cuando queden muy pocas libres?
Imagina que seguimos esta estrategia en un tablero de 1000 por 1000 casillas. Cuando
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

solo queden dos libres, es probable que tengamos que generar muchsimas tiradas de
dado hasta dar con una casilla libre: la probabilidad de que demos con una de ellas es
de una contra medio milln. Eso significa que, en promedio, har falta echar medio milln
de veces los dados para encontrar una casilla libre. Ineficiente a ms no poder.

Creamos una lista con todos los pares de coordenadas posibles, o sea, una lista de listas:
0 0
0 1
0 2
3 5 . A continuacin, desordenamos la lista. Cmo?
Escogiendo muchas veces (por ejemplo, mil veces) un par de elementos de la lista e
intercambindolos. Una vez desordenada la lista, la usamos para asignar los caracteres:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16

def rellena_smbolos smbolo


Segunda versin.
lista
for i in range len smbolo
for j in range len smbolo 0
lista append
i j
for i in range 1000
i j
randrange len smbolo
aux
lista i
lista i
lista j
lista j
aux
i
0
for coords in lista
smbolo coords 0
i
1

randrange len smbolo 0

coords 1

Complicado, verdad? No solo es complicado; adems, presenta un serio inconveniente: un


elevado (y gratuito) consumo de memoria. Imagina que la matriz tiene dimensin 1000
1000: hemos de construir una lista con un milln de elementos y barajarlos (para lo que
necesitaremos bastante ms que 1000 intercambios). Una lista tan grande ocupa mucha
memoria. La siguiente solucin es igual de efectiva y no consume tanta memoria.
Ponemos las letras ordenadamente en la matriz. Despus, intercambiamos mil veces un
par de casillas escogidas al azar:
1
2
3
4
5
6
7
8
9

10
11
12
13

def rellena_smbolos smbolo


Tercera versin.
numsmbolo
0
for i in range len smbolo
for j in range len smbolo 0
smbolo i j
chr ord
numsmbolo
numsmbolo
1
for i in range 1000
f1 c1
randrange len smbolo
f2 c2
randrange len smbolo
tmp
smbolo f1 c1
smbolo f1 c1
smbolo f2 c2
smbolo f2 c2
tmp

randrange len smbolo 0


randrange len smbolo 0

Estudia con cuidado esta funcin. Es la que vamos a usar en nuestro programa.

Bueno. Ya le hemos dedicado bastante tiempo a la inicializacin de la matriz de smbolos. Ahora


vamos a dibujar en pantalla su contenido. Necesitamos inicializar la pantalla y la tortuga con
la que dibujaremos todo.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19

Programa principal
filas
4
columnas
6

pantalla
Screen
pantalla setup columnas 50 filas 50
pantalla screensize columnas 50 filas 50
pantalla setworldcoordinates .5
.5 columnas .5
pantalla delay 0
tortuga
Turtle
tortuga hideturtle
smbolo
crea_matriz filas columnas
tablero
crea_matriz filas columnas

filas .5

inicializa_tablero tablero
rellena_smbolos smbolo
dibuja_tablero tablero smbolo

El procedimiento dibuja_tablero recibe las matrices con el estado de las celdas y los smbolos
y hace algo muy sencillo: recurre a otra funcin para dibujar cada una de las celdas en el estado
en el que se encuentre:
1
2
3
4

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20

def dibuja_tablero tablero smbolo


for i in range len smbolo
for j in range len smbolo 0
dibuja_celda tablero smbolo

La funcin dibuja_celda es la responsable de dibujar el contenido de cada celda individual:

def dibuja_celda baldosa smbolo i j


global tortuga
tortuga penup
tortuga goto j .5 i
tortuga begin_fill
if baldosa i j
CeldaCerrada
tortuga fillcolor
tortuga circle .5
elif baldosa i j
CeldaAbierta
tortuga fillcolor
tortuga circle .5
tortuga goto j .5 i .25
tortuga write smbolo i j
else
tortuga fillcolor
tortuga circle .5
tortuga goto j .5 i .25
tortuga write smbolo i j
tortuga end_fill
tortuga pendown

Hemos recurrido a mtodos de la tortuga que an no conoces. Veamos qu hacen:


tortuga begin_fill
tortuga end_fill

: Inicia un polgono relleno.

: Rellena el polgono iniciado con tortuga begin_fill

tortuga fill_color color : Hace que el color de relleno sea el que se especifica con una
cadena como argumento.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Pongamos en un nico fichero todo lo que hemos hecho de momento.


1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

from random import randrange


from turtle import Screen Turtle
CeldaCerrada
0
CeldaAbierta
1
CeldaTemporalmenteAbierta

def crea_matriz filas columnas


matriz
for i in range filas
matriz append None
return matriz

columnas

def rellena_smbolos smbolo


Tercera versin.
numsmbolo
0
for i in range len smbolo
for j in range len smbolo 0
smbolo i j
chr ord
numsmbolo
numsmbolo
1
for i in range 1000
f1 c1
randrange len smbolo
f2 c2
randrange len smbolo
tmp
smbolo f1 c1
smbolo f1 c1
smbolo f2 c2
smbolo f2 c2
tmp

randrange len smbolo 0


randrange len smbolo 0

def inicializa_tablero tablero


for i in range len tablero
for j in range len tablero 0
tablero i j
CeldaCerrada

def dibuja_tablero tablero smbolo


for i in range len smbolo
for j in range len smbolo 0
dibuja_celda tablero smbolo
def dibuja_celda baldosa smbolo i j
global tortuga
tortuga penup
tortuga goto j .5 i
tortuga begin_fill
if baldosa i j
CeldaCerrada
tortuga fillcolor
tortuga circle .5
elif baldosa i j
CeldaAbierta
tortuga fillcolor
tortuga circle .5
tortuga goto j .5 i .25
tortuga write smbolo i j
else
tortuga fillcolor
tortuga circle .5
tortuga goto j .5 i .25
tortuga write smbolo i j
tortuga end_fill
tortuga pendown

Programa principal

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

filas
4
columnas

pantalla
Screen
pantalla setup columnas 50 filas 50
pantalla screensize columnas 50 filas 50
pantalla setworldcoordinates .5
.5 columnas .5
pantalla delay 0
tortuga
Turtle
tortuga hideturtle
smbolo
crea_matriz filas columnas
tablero
crea_matriz filas columnas

filas .5

inicializa_tablero tablero
rellena_smbolos smbolo
dibuja_tablero tablero smbolo
pantalla exitonclick

Ejecuta el programa y vers en pantalla el tablero de juego como una simple matriz de
crculos azules. Vamos ya a por lo difcil: la interaccin con el ratn. El modo de trabajar es
un tanto especial. Definiremos una funcin a la que el sistema llamar automticamente cada
vez que se produzca un clic de ratn. La funcin debe tener dos parmetros: las coordenadas
del punto en el que se ha producido el clic de ratn (expresada en las coordenadas de pantalla
que hemos definido). Hagamos, de momento, que la funcin escriba las coordenadas de la celda
seleccionada:
1
2
3

def clic x
j i
print

int x

int y

format i

Tendremos que conectar la funcin con el evento de ratn a travs del mtodo pantalla onclick. El mtodo pantalla onclick admite como argumento una funcin: la que queremos
que se llame automticamente cada vez que se pulsa el botn del ratn. El cableado del evento
a la funcin que hemos definido tiene lugar en el programa principal:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23

Programa principal
filas
4
columnas
6

pantalla
Screen
pantalla setup columnas 50 filas 50
pantalla screensize columnas 50 filas 50
pantalla setworldcoordinates .5
.5 columnas .5
pantalla delay 0
tortuga
Turtle
tortuga hideturtle
smbolo
crea_matriz filas columnas
tablero
crea_matriz filas columnas

filas .5

inicializa_tablero tablero
rellena_smbolos smbolo
dibuja_tablero tablero smbolo
pantalla onclick clic
pantalla mainloop

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Observa, adems, cmo hemos cambiado la ltima lnea del programa principal. Ya no interesa
que la ejecucin del programa finalice cuando se hace clic en cualquier lugar de la pantalla,
pues vamos a tratar los clics con nuestro cdigo. El mtodo pantalla mainloop hace que el
programa entre en un bucle de control propio que le obliga a esperar eventos y tratarlos cuando
se producen.
La mayor complicacin del cdigo va a la funcin clic. Vamos con ella:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

def clic x y
global tablero smbolo temporal1 temporal2
j i
int x
int y
if 0
i
len smbolo and 0
j
len smbolo 0
if tablero i j
CeldaCerrada
if temporal1
None
temporal1
i j
tablero i j
CeldaTemporalmenteAbierta
else
temporal2
i j
tablero i j
CeldaTemporalmenteAbierta
dibuja_celda tablero smbolo i j
if temporal2
None
if smbolo temporal1 0
temporal1 1
smbolo temporal2 0
temporal2 1
tablero temporal1 0
temporal1 1
tablero temporal2 0
temporal2 1
else
tablero temporal1 0
temporal1 1
tablero temporal2 0
temporal2 1
dibuja_celda tablero smbolo temporal1 0
dibuja_celda tablero smbolo temporal2 0
temporal1
None
temporal2
None
dibuja_celda tablero smbolo i j
temporal1
temporal2

CeldaAbierta
CeldaAbierta

CeldaCerrada
CeldaCerrada
temporal1 1
temporal2 1

None
None

Nos estamos apoyando en dos variables, temporal1 y temporal2, que almacenan las coordenadas de las celdas descubiertas temporalmente. Cuando temporal1 vale None, es que no hay
ninguna celda temporalmente abierta; y cuando temporal1 tiene otro valor y temporal2 es None,
solo hay una celda temporalmente abierta. Tras comprobar que la pulsacin tiene lugar en una
celda vlida y que esta est tapada, vemos si es la primera celda de la pareja que vamos a
descubrir o si, por el contrario, es la segunda. En cualquier caso memorizamos sus coordenadas.
Si es la segunda, comprobamos si las dos celdas descubiertas contienen la misma letra. Si es
as, las marcamos como descubiertas. Si no, las dejamos como estaban y dejamos de considerar
a ambas como temporalmente descubiertas. Finalmente, actualizamos el dibujo en pantalla. Lee
el cuerpo de la funcin paso a paso para asegurarte de que lo entiendes.
Si ejecutas el programa vers que tiene un pequeo fallo: cuando pulsas en la segunda
casilla cuya letra quieres ver, no da tiempo material de verla, pues la celda se redibuja como
cerrada instantneamente. Hemos de introducir algn retardo. Hay un modo elegante de hacer
una pausa: con la funcin sleep del mdulo time. Si llamamos a la funcin con un nmero en
coma flotante, el programa se detendr ese nmero de segundos al ejecutarla:
1
2
3

from time import sleep

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

def clic x y
global tablero smbolo temporal1 temporal2
j i
int x
int y
if 0
i
len smbolo and 0
j
len smbolo 0
if tablero i j
CeldaCerrada
if temporal1
None
temporal1
i j
tablero i j
CeldaTemporalmenteAbierta
else
temporal2
i j
tablero i j
CeldaTemporalmenteAbierta
dibuja_celda tablero smbolo i j
if temporal2
None
if smbolo temporal1 0
temporal1 1
smbolo temporal2 0
temporal2 1
tablero temporal1 0
temporal1 1
tablero temporal2 0
temporal2 1
else
sleep 0.5
tablero temporal1 0
temporal1 1
tablero temporal2 0
temporal2 1
dibuja_celda tablero smbolo temporal1 0
dibuja_celda tablero smbolo temporal2 0
temporal1
None
temporal2
None
dibuja_celda tablero smbolo i j
temporal1
temporal2

CeldaAbierta
CeldaAbierta

CeldaCerrada
CeldaCerrada
temporal1 1
temporal2 1

None
None

Ya casi est. Nos falta controlar el final de la partida todas las celdas estn abiertas
y, ya puestos, pulir un detalle: cuando se est ejecutando la funcin clic hemos de desconectar
momentneamente el tratamiento de eventos. Si no lo hacemos, es posible que se ejecute una
llamada a clic mientras hay otra llamada a clic en ejecucin. El resultado puede ser desastroso.
Este es el programa final:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23

from random import randrange


from turtle import Screen Turtle
from time import sleep
CeldaCerrada
0
CeldaAbierta
1
CeldaTemporalmenteAbierta

def crea_matriz filas columnas


matriz
for i in range filas
matriz append None
return matriz

columnas

def rellena_smbolos smbolo


Tercera versin.
numsmbolo
0
for i in range len smbolo
for j in range len smbolo 0
smbolo i j
chr ord
numsmbolo
numsmbolo
1
for i in range 1000
f1 c1
randrange len smbolo

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

randrange len smbolo 0


Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

f2 c2
randrange len smbolo
tmp
smbolo f1 c1
smbolo f1 c1
smbolo f2 c2
smbolo f2 c2
tmp

randrange len smbolo 0

def inicializa_tablero tablero


for i in range len tablero
for j in range len tablero 0
tablero i j
CeldaCerrada

def dibuja_tablero tablero smbolo


for i in range len smbolo
for j in range len smbolo 0
dibuja_celda tablero smbolo
def dibuja_celda baldosa smbolo i j
global tortuga
tortuga penup
tortuga goto j .5 i
tortuga begin_fill
if baldosa i j
CeldaCerrada
tortuga fillcolor
tortuga circle .5
elif baldosa i j
CeldaAbierta
tortuga fillcolor
tortuga circle .5
tortuga goto j .5 i .25
tortuga write smbolo i j
else
tortuga fillcolor
tortuga circle .5
tortuga goto j .5 i .25
tortuga write smbolo i j
tortuga end_fill
tortuga pendown

def clic x y
global pantalla tablero smbolo temporal1 temporal2
pantalla onclick None
j i
int x
int y
if 0
i
len tablero and 0
j
len tablero 0
if tablero i j
CeldaCerrada
if temporal1
None
temporal1
i j
tablero i j
CeldaTemporalmenteAbierta
else
temporal2
i j
tablero i j
CeldaTemporalmenteAbierta
dibuja_celda tablero smbolo i j
if temporal2
None
if smbolo temporal1 0
temporal1 1
smbolo temporal2 0
temporal2 1
tablero temporal1 0
temporal1 1
CeldaAbierta
tablero temporal2 0
temporal2 1
CeldaAbierta
else
sleep 0.5
tablero temporal1 0
temporal1 1
CeldaCerrada
tablero temporal2 0
temporal2 1
CeldaCerrada
dibuja_celda tablero smbolo temporal1 0
temporal1 1
dibuja_celda tablero smbolo temporal2 0
temporal2 1
temporal1
None

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

temporal2
None
dibuja_celda tablero smbolo

85
86
87

if todas_abiertas tablero
pantalla bye
else
pantalla onclick clic

88
89
90
91
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

def todas_abiertas tablero


for i in range len tablero
for j in range len tablero 0
if tablero i j
CeldaCerrada
return False
return True
Programa principal
filas
4
columnas
6

pantalla
Screen
pantalla setup columnas 50 filas 50
pantalla screensize columnas 50 filas 50
pantalla setworldcoordinates .5
.5 columnas .5
pantalla delay 0
tortuga
Turtle
tortuga hideturtle
smbolo
crea_matriz filas columnas
tablero
crea_matriz filas columnas

filas .5

temporal1
None
temporal2
None
inicializa_tablero tablero
rellena_smbolos smbolo
dibuja_tablero tablero smbolo
pantalla onclick clic
pantalla mainloop

338

Modifica Memorin para que se ofrezca al usuario jugar con tres niveles de dificultad:

Fcil: tablero de 3 4.

Normal: tablero de 4 6.
Difcil: tablero de 6 8.

339
Implementa Memorin3, una variante de Memorin en la que hay que emparejar
grupos de 3 letras iguales. (Asegrate de que el nmero de casillas de la matriz sea mltiplo
de 3).

340
Construye el programa del Buscaminas inspirndote en la forma en que hemos
desarrollado el juego Memorin. Te damos unas pistas para ayudarte en la implementacin:

Crea una matriz cuyas casillas contengan el valor True o False. El primer valor indica
que hay una mina en esa casilla. Ubica las minas al azar. El nmero de minas depender
de la dificultad del juego.

Crea una matriz que contenga el nmero de minas que rodean a cada casilla. Calcula esos
valores a partir de la matriz de minas. Ojo con las casillas especiales: el nmero de
vecinos de las casillas de los bordes requiere un cuidado especial.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Dibuja las minas y baldosas que las tapan. Define adecuadamente el sistema de coordenadas del lienzo.
El programa principal es un bucle similar al de Memorin. El bucle principal finaliza
cuando hay una coincidencia total entre la matriz de minas y la matriz de marcas puestas
por el usuario.

Cada vez que se pulse el botn del ratn, destruye la baldosa correspondiente. Si esta
esconda una mina, la partida ha acabado y el jugador ha muerto. Si no, crea un objeto
grfico (texto) que muestre el nmero de minas vecinas a esa casilla.

341
Modifica el Buscaminas para que cada vez que se pulse con el primer botn en una
casilla con cero bombas vecinas, se marquen todas las casillas alcanzables desde esta y que no
tienen bomba. (Este ejercicio es difcil. Piensa bien en la estrategia que has de seguir).
342

Disea un programa que permita jugar a dos personas al tres en raya.

343
Disea un programa que permita jugar al tres en raya enfrentando a una persona al
ordenador. Cuando el ordenador empiece una partida, debe ganarla siempre. (Este ejercicio es
difcil. Si no conoces la estrategia ganadora, bscala en Internet).

344
Disea un programa que permita que dos personas jueguen a las damas. El programa
debe verificar que todos los movimientos son vlidos.

345
Disea un programa que permita que dos personas jueguen al ajedrez. El programa
debe verificar que todos los movimientos son vlidos.

6.6.

Ejemplos

6.6.1.

Integracin numrica

Vamos ahora a desarrollar unos cuantos ejemplos de programas con funciones. As pondremos
en prctica lo aprendido.
Vamos a implementar un programa de integracin numrica que aproxime el valor de

con la frmula

n1

i=0

x 2 dx

x (a + i x)2 ,

donde x = (b a)/n. El valor de n lo proporcionamos nosotros: a mayor valor de n, mayor


precisin en la aproximacin. Este mtodo de aproximacin de integrales se basa en el clculo
del rea de una serie de rectngulos.
En la grfica de la izquierda de la figura que aparece a continuacin se marca en gris
la regin cuya rea corresponde al valor de la integral de x 2 entre a y b. En la grfica de la
derecha se muestra en gris el rea de cada uno de los 6 rectngulos (n = 6) utilizados en
la aproximacin. La suma de las 6 reas es el resultado de nuestra aproximacin. Si en lugar de
6 rectngulos ussemos 100, el valor calculado sera ms aproximado al real.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

x2

x2

La funcin Python que vamos a definir se denominar integral_x2 y necesita tres datos de
entrada: el extremo izquierdo del intervalo (a), el extremo derecho (b) y el nmero de rectngulos
con los que se efecta la aproximacin (n).
La cabecera de la definicin de la funcin ser, pues, de la siguiente forma:
1
2

def integral_x2 a

Qu ponemos en el cuerpo? Pensemos. En el fondo, lo que se nos pide no es ms que el


clculo de un sumatorio. Los elementos que participan en el sumatorio son un tanto complicados,
pero esta complicacin no afecta a la forma general de clculo de un sumatorio. Los sumatorios
se calculan siguiendo un patrn que ya hemos visto con anterioridad:
1
2
3
4

def integral_x2 a b n
sumatorio
0.0
for i in range n
sumatorio
lo que sea

Ese lo que sea es, precisamente, la frmula que aparece en el sumatorio. En nuestro caso,
ese fragmento del cuerpo de la funcin ser as:
1
2
3
4

def integral_x2 a b n
sumatorio
0.0
for i in range n
sumatorio
deltax

deltax

def integral_x2 a b n
deltax
b a
n
sumatorio
0.0
for i in range n
sumatorio
deltax

deltax

Mmmm. . . En el bucle hacemos uso de una variable deltax que, suponemos, tiene el valor
de x. As pues, habr que calcular previamente su valor:
1
2
3
4
5

1
2
3
4

La variable deltax (al igual que i y sumatorio) es una variable local.


Ya casi est. Faltar aadir una lnea: la que devuelve el resultado.

def integral_x2 a b n
deltax
b a
n
sumatorio
0.0
for i in range n

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

sumatorio
deltax
return sumatorio

5
6

deltax

Hecho? Repasemos, a ver si todo est bien. Fjate en la lnea 2. Esa expresin puede dar
problemas si n vale 0. Debemos evitar la divisin por cero. Si n vale cero, el resultado de la
integral ser 0.
1
2
3

4
5
6
7
8
9

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16

def integral_x2 a b n
if n
0
sumatorio
0.0
else
deltax
b a
n
sumatorio
0.0
for i in range n
sumatorio
deltax
return sumatorio

deltax

deltax

Ya podemos utilizar nuestra funcin:

def integral_x2 a b n
if n
0
sumatorio
0.0
else
deltax
b a
n
sumatorio
0.0
for i in range n
sumatorio
deltax
return sumatorio
inicio
float input
final
float input
partes
int input

print
print

format inicio final


end
format integral_x2 inicio final partes

En la lnea 16 llamamos a integral_x2 con los argumentos inicio, final y partes, variables
cuyo valor nos suministra el usuario en las lneas 1113. Recuerda que cuando llamamos a
una funcin, Python asigna a cada parmetro el valor de un argumento siguiendo el orden de
izquierda a derecha. As, el parmetro a recibe el valor que contiene el argumento inicio, el
parmetro b recibe el valor que contiene el argumento final y el parmetro n recibe el valor que
contiene el argumento partes. No importa cmo se llama cada argumento. Una vez se han hecho
esas asignaciones, empieza la ejecucin de la funcin.

6.6.2.

Aproximacin de la exponencial de un nmero real

Vamos a desarrollar una funcin que calcule el valor de ea , siendo a un nmero real, con
una restriccin: no podemos utilizar el operador de exponenciacin .
Si a fuese un nmero natural, sera fcil efectuar el clculo:
1
2
3
4
5
6
7

from math import e

def exponencial a
exp
1.0
for i in range a
exp
e
return exp

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Un mtodo de integracin genrico

El mtodo de integracin que hemos implementado presenta un inconveniente: solo puede usarse
para calcular la integral definida de una sola funcin: f (x) = x 2 . Si queremos integrar, por ejemplo,
g(x) = x 3 , tendremos que codificar otra vez el mtodo y cambiar una lnea. Y por una sla lnea
hemos de volver a escribir otras ocho?
Analiza este programa:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21

def cuadrado x
return x 2
def cubo x
return x

def integral_definida f a b n
if n
0
sumatorio
0.0
else
deltax
b a
n
sumatorio
0.0
for i in range n
sumatorio
deltax
return sumatorio
a
1
b
2
print
print
print

f a

deltax

format a b
integral_definida cuadrado a b 100
integral_definida cubo a b 100

Podemos pasar funciones como argumentos! En la lnea 20 calculamos la integral de x 2 entre


1 y 2 (con 100 rectngulos) y en la lnea 21, la de x 3 . Hemos codificado una sola vez el mtodo de
integracin y es, en cierto sentido, genrico: puede integrar cualquier funcin.
Pon atencin a este detalle: cuando pasamos la funcin como parmetro, no usamos parntesis con
argumentos; solo pasamos el nombre de la funcin. El nombre de la funcin es una variable. Y qu
contiene? Contiene una referencia a una zona de memoria en la que se encuentran las instrucciones
que hemos de ejecutar al llamar a la funcin. Leer ahora el cuadro Los parntesis son necesarios
puede ayudarte a entender esta afirmacin.

346
Y si a pudiera tomar valores enteros negativos? Disea una funcin exponencial que
trate tambin ese caso. (Recuerda que ea = 1/ea ).

Pero siendo a un nmero real (bueno, un flotante), no nos vale esa aproximacin. Refrescando
conocimientos matemticos, vemos que podemos calcular el valor de ea para a real con la
siguiente frmula:
ea = 1 + a +

 an
a3
a4
ak
a2
+
+
+ +
+ =
.
2
3!
4!
k!
n!

n=0

La frmula tiene un nmero infinito de sumandos, as que no la podemos codificar en Python.


Haremos una cosa: disearemos una funcin que aproxime el valor de ea con tantos sumandos
como nos indique el usuario.
Vamos con una primera versin:
E
1
2
3

def exponencial a n
sumatorio
0.0
for k in range n

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

4
5

sumatorio
a
return sumatorio

Mmmm. Mal. Por una parte, nos han prohibido usar el operador
efectuar el correspondiente clculo de otro modo. Recuerda que
ak =

E
1
2
3
4
5
6
7
8
9

10

k

i=1

, as que tendremos que

a.

def exponencial a n
sumatorio
0.0
for k in range n
Clculo de a elevado a k.
numerador
1.0
for i in range 1 k 1
numerador
a
Adicin de nuevo sumando al sumatorio.
sumatorio
numerador
k
return sumatorio

Y por otra parte, no hay operador factorial en Python. Tenemos que calcular el factorial
explcitamente. Recuerda que

1
2
3
4
5
6
7
8
9

10
11
12
13
14

1
2
3
4
5
6
7
8
9

10
11

Corregimos el programa anterior:

k! =

k

i=1

i.

def exponencial a n
sumatorio
0.0
for k in range n
Clculo de a elevado a k.
numerador
1.0
for i in range 1 k 1
numerador
a
Clculo de k factorial.
denominador
1.0
for i in range 1 k 1
denominador
i
Adicin de nuevo sumando al sumatorio.
sumatorio
numerador
denominador
return sumatorio

Y ya est. La verdad es que no queda muy legible. Analiza esta otra versin:

def elevado a k
productorio
1.0
for i in range 1 k 1
productorio
a
return productorio
def factorial k
productorio
1.0
for i in range 1 k 1
productorio
i
return productorio

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

12
13
14
15
16
17

def exponencial a n
sumatorio
0.0
for k in range n
sumatorio
elevado a
return sumatorio

factorial k

Esta versin es mucho ms elegante que la anterior, e igual de correcta. Al haber separado
el clculo de la exponenciacin y del factorial en sendas funciones hemos conseguido que la
funcin exponencial sea mucho ms legible.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

347

Es correcta esta otra versin?

def elevado a k
productorio
1.0
for i in range k
productorio
a
return productorio

def factorial k
productorio
1.0
for i in range 2 k 1
productorio
i
return productorio

def exponencial a n
sumatorio
0.0
for k in range n
sumatorio
elevado a
return sumatorio

348

factorial k

Las funciones seno y coseno se pueden calcular as


sin(x)

cos(x)

x
1

 (1)n x 2n+1
x5
x7
x3
+

+ =
3!
5!
7!
(2n + 1)!

x
x
x
+

+ =
2!
4!
6!

n=0


(1)n x 2n
n=0

(2n)!

Disea sendas funciones seno y coseno para aproximar, respectivamente, el seno y el coseno de
x con n trminos del sumatorio correspondiente.

El mtodo de clculo que hemos utilizado en la funcin exponencial es ineficiente: el trmino elevado a k
factorial k resulta costoso de calcular. Imagina que nos piden calcular
exponencial a 8 . Se producen las siguientes llamadas a elevado y factorial:
elevado a

0 y factorial 0 .

elevado a

2 y factorial 2 .

elevado a
elevado a
elevado a
elevado a

1 y factorial 1 .
3 y factorial 3 .
4 y factorial 4 .
5 y factorial 5 .

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

elevado a
elevado a

6 y factorial 6 .
7 y factorial 7 .

Estas llamadas esconden una repeticin de clculos que resulta perniciosa para la velocidad de
ejecucin del clculo. Cada llamada a una de esas rutinas supone iterar un bucle, cuando resulta
innecesario si aplicamos un poco de ingenio. Fjate en que se cumplen estas dos relaciones:
elevado(a, n) = aelevado(a, n 1),

factorial(n) = nfactorial(n 1),

para todo n mayor que 0. Si n vale 0, tanto elevado a n como factorial n valen 1. Este
programa te muestra el valor de elevado 2 n para n entre 0 y 7:
1
2
3
4
5
6

a
2
valor
1
print
for n in range 1 8
valor
a
valor
print

349
1
2
3
4
5
6
7
8
9

format a

format a

valor
n

valor

Disea un programa similar que muestre el valor de factorial n para n entre 0 y 7.

Explotemos esta forma de calcular esa serie de valores en el cmputo de exponencial:

def exponencial a n
numerador
1
denominador
1
sumatorio
1.0
for k in range 1 n
numerador
a
numerador
denominador
k
denominador
sumatorio
numerador
denominador
return sumatorio

350
Modifica las funciones que has propuesto como solucin al ejercicio 348 aprovechando
las siguientes relaciones, vlidas para n mayor que 0:
(1)n x 2n+1
(2n + 1)!
(1)n x 2n
(2n)!

Cuando n vale 0, tenemos:

x 2
(2n + 1) 2n
x 2
2n (2n 1)

(1)0 x 1
= x,
1!

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

(1)n1 x 2(n1)+1
,
(2(n 1) + 1)!
(1)n1 x 2(n1)

.
(2(n 1))!

(1)0 x 0
= 1.
0!
Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Resolvamos ahora un problema ligeramente diferente: vamos a aproximar ea con tantos trminos como sea preciso hasta que el ltimo trmino considerado sea menor o igual que un
valor dado. Lo desarrollaremos usando, de nuevo, las funciones elevado y factorial. (Enseguida
te pediremos que mejores el programa con las ltimas ideas presentadas). No resulta apropiado
ahora utilizar un bucle for in, pues no sabemos cuntas iteraciones habr que dar hasta llegar
a un ak /k! menor o igual que . Utilizaremos un bucle while:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21

def elevado a k
productorio
1.0
for i in range k
productorio
a
return productorio

def factorial n
productorio
1.0
for i in range 1 n 1
productorio
i
return productorio

def exponencial2 a psilon


sumatorio
0.0
k
0
trmino
elevado a k
factorial k
while trmino
psilon
sumatorio
trmino
k
1
trmino
elevado a k
factorial k
return sumatorio

351
Modifica la funcin exponencial2 del programa anterior para que no se efecten las
ineficientes llamadas a elevado y factorial.

6.6.3.

Clculo de nmeros combinatorios

Ahora vamos a disear una funcin que calcule de cuntas formas podemos escoger m
elementos de un conjunto con n objetos. Recuerda que la frmula es:
 
n!
n
=
m
(n m)! m!

Esta funcin es fcil de codificar. . . si reutilizamos la funcin factorial del apartado anterior!
1
2
3
4
5
6
7
8

def factorial n
productorio
1.0
for i in range 1 n 1
productorio
i
return productorio
def combinaciones n m
return factorial n

factorial n m

factorial m

Observa cun apropiado ha resultado que factorial fuera una funcin definida independientemente: hemos podido utilizarla en tres sitios diferentes con solo invocarla. Adems, una vez
diseada la funcin factorial, podemos reutilizarla en otros programas con solo copiar y pegar.
Ms adelante te ensearemos cmo hacerlo an ms cmodamente.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6.6.4.

El mtodo de la biseccin

El mtodo de la biseccin permite encontrar un cero de una funcin matemtica f (x) en un


intervalo [a, b] si f (x) es continua en dicho intervalo y f (a) y f (b) son de distinto signo.
El mtodo de la biseccin consiste en dividir el intervalo en dos partes iguales. Llamemos c
al punto medio del intervalo. Si el signo de f (c) tiene el mismo signo que f (a), aplicamos el
mismo mtodo al intervalo [c, b]. Si f (c) tiene el mismo signo que f (b), aplicamos el mtodo de
la biseccin al intervalo [a, c]. El mtodo finaliza cuando hallamos un punto c tal que f (c) = 0
o cuando la longitud del intervalo de bsqueda es menor que un determinado.
En la figura de la izquierda te mostramos el instante inicial de la bsqueda: nos piden hallar
un cero de una funcin continua f entre a y b y ha de haberlo porque el signo de f (a) es distinto
del de f (b). Calculamos entonces el punto medio c entre a y b. f (c) y f (b) presentan el mismo
signo, as que el cero no se encuentra entre c y b, sino entre a y c. La figura de la derecha te
muestra la nueva zona de inters: b ha cambiado su valor y ha tomado el que tena c.
f (b)

f (a)

f (c)
c

f (a)

f (b)
b

Deseamos disear un programa que aplique el mtodo de la biseccin a la bsqueda de un


cero de la funcin f (x) = x 2 2x 2 en el intervalo [0.5, 3.5]. No debemos considerar intervalos
de bsqueda mayores que 105 .
Parece claro que implementaremos dos funciones: una para la funcin matemtica f (x) y
otra para el mtodo de la biseccin. Esta ltima tendr tres parmetros: los dos extremos del
intervalo y el valor de que determina el tamao del (sub)intervalo de bsqueda ms pequeo
que queremos considerar:
1
2
3
4
5

def f x
return x

def biseccin a

2 x

psilon

El mtodo de la biseccin es un mtodo iterativo: aplica un mismo procedimiento repetidas


veces hasta satisfacer cierta condicin. Utilizaremos un bucle, pero un while o un for in? Obviamente, un bucle while: no sabemos a priori cuntas veces iteraremos. Cmo decidimos cundo
hay que volver a iterar? Hay que volver a iterar mientras no hayamos hallado el cero y, adems,
el intervalo de bsqueda sea mayor que :
1
2
3
4
5
6

def f x
return x

def biseccin a
while f c

2 x

psilon
0 and b

psilon

Para que la primera comparacin funcione c ha de tener asignado algn valor:

def f x

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

2
3
4
5
6
7

return x

2 x

def biseccin a b psilon


c
a
b
2
while f c
0 and b

psilon

Parmetros con valor por defecto

La funcin biseccin trabaja con tres parmetros. El tercero est relacionado con el margen de
error que aceptamos en la respuesta. Supn que el noventa por cien de las veces trabajamos con
un valor de fijo, pongamos que igual a 105 . Puede resultar pesado proporcionar explcitamente ese
valor en todas y cada una de las llamadas a la funcin. Python nos permite proporcionar parmetros
con un valor por defecto. Si damos un valor por defecto al parmetro psilon, podremos llamar a la
funcin biseccin con tres argumentos, como siempre, o con solo dos.
El valor por defecto de un parmetro se declara en la definicin de la funcin:
1
2

def biseccin a

psilon 1e 5

Si llamamos a la funcin mediante biseccin 1 2 , es como si la hubisemos llamado as:


biseccin 1 2 1e 5 . Al no indicar valor para psilon, Python toma su valor por defecto.

1
2
3
4
5
6
7
8
9

10
11

Dentro del bucle hemos de actualizar el intervalo de bsqueda:

def f x
return x

2 x

def biseccin a b psilon


c
a
b
2
while f c
0 and b
a
if f a
0 and f c
a
c
elif f b
0 and f c
b
c

psilon
0
or f a
0

or

f b

0 and f c

0 and f c

Las condiciones del if elif son complicadas. Podemos simplificarlas con una idea feliz: dos
nmeros x e y tienen el mismo signo si su producto es positivo.
1
2
3
4
5
6
7
8
9

10
11

def f x
return x

2 x

def biseccin a b psilon


c
a
b
2
while f c
0 and b
a
if f a
f c
0
a
c
elif f b
f c
0
b
c

psilon

An nos queda preparar la siguiente iteracin. Si no actualizamos el valor de c, la funcin


quedar atrapada en un bucle sin fin. Ah! Y al finalizar el bucle hemos de devolver el cero de
la funcin:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4
5
6
7
8
9

10
11
12

1
2
3
4
5
6
7
8
9

10
11
12
13
14

def f x
return x

2 x

def biseccin a b psilon


c
a
b
2
while f c
0 and b
a
if f a
f c
0
a
c
elif f b
f c
0
b
c
c
a
b
2
return c

psilon

Ya podemos completar el programa introduciendo el intervalo de bsqueda y el valor de :

def f x
return x

2 x

def biseccin a b psilon


c
a
b
2
while f c
0 and b
a
if f a
f c
0
a
c
elif f b
f c
0
b
c
c
a
b
2
return c
print

psilon

biseccin 0.5

3.5

1e 5

352
La funcin biseccin an no est acabada del todo. Qu ocurre si el usuario introduce
un intervalo [a, b] tal que f (a) y f (b) tienen el mismo signo? Y si f (a) o f (b) valen 0? Modifica la
funcin para que solo inicie la bsqueda cuando procede y, en caso contrario, devuelva el valor
especial None. Si f (a) o f (b) valen cero, biseccin devolver el valor de a o b, segn proceda.

353
Modifica el programa para que solicite al usuario los valores a, b y . El programa
solo aceptar valores de a y b tales que a < b.

6.7.

Diseo de programas con funciones

Hemos aprendido a disear funciones, cierto, pero puede que no tengas claro qu ventajas
nos reporta trabajar con ellas. El programa de integracin numrica que hemos desarrollado en
la seccin anterior podra haberse escrito directamente as:
1
2
3
4
5
6
7
8
9

10
11

a
b
n

if n

else

float input
float input
int input

0
sumatorio

0.0

deltax
b
a
n
sumatorio
0.0
for i in range n
sumatorio
deltax

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

deltax

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Evita las llamadas repetidas

En nuestra ltima versin del programa


un c fijo, se calcula 3 veces por iteracin.
1
2
3
4
5
6
7
8
9

10
11
12

def f x
return x

2 x

hay una fuente de ineficiencia: f c , para

def biseccin a b psilon


c
a
b
2
while f c
0 and b
a
if f a
f c
0
a
c
elif f b
f c
0
b
c
c
a
b
2
return c

psilon

Llamar a una funcin es costoso: se debe dedicar un tiempo a gestionar la pila de llamadas apilando una nueva trama de activacin (y ocupar, en consecuencia, algo de memoria), copiar referencias
a los valores de los argumentos en los parmetros formales, efectuar un clculo que posiblemente ya
hayamos hecho y devolver el valor resultante. Una optimizacin del programa consiste en no llamar
a f c ms que una vez y almacenar el resultado en una variable temporal que usaremos cada vez
que deberamos haber llamado a f c :
1
2
3
4
5
6
7
8
9

10
11

12
13
14

def biseccin a b psilon


c
a
b
2
fc
f c
while fc
0 and b
a
if f a
fc
0
a
c
elif f b
fc
0
b
c
c
a
b
2
fc
f c
return c

psilon

print
print

end
format a

sumatorio

Este programa ocupa menos lneas y hace lo mismo, no? S, as es. Con programas pequeos
como este apenas podemos apreciar las ventajas de trabajar con funciones. Imagina que el
programa fuese mucho ms largo y que hiciese falta aproximar el valor de la integral definida
de x 2 en tres o cuatro lugares diferentes; entonces s que sera una gran ventaja haber definido
una funcin: habiendo escrito el procedimiento de clculo una vez podramos ejecutarlo cuantas
veces quisiramos mediante simples invocaciones. No solo eso, habramos ganado en legibilidad.

6.7.1.

Ahorro de tecleo

Por ejemplo, supn que en un programa deseamos leer tres nmeros enteros y asegurarnos
de que sean positivos. Podemos proceder repitiendo el bucle correspondiente tres veces:
1
2
3
4

a
int input
while a
0
print
a
int input

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5
6
7
8
9

10
11
12
13
14

b
int input
while b
0
print
b
int input
c
int input
while c
0
print
c
int input

O podemos llamar tres veces a una funcin que lea un nmero y se asegure de que sea
positivo:
1
2
3
4
5
6
7
8
9

10

def lee_entero_positivo texto


nmero
int input texto
while nmero
0
print
nmero
int input texto
return nmero
a
b
c

lee_entero_positivo
lee_entero_positivo
lee_entero_positivo

Hemos reducido el nmero de lneas, as que hemos tecleado menos. Ahorrar tecleo tiene
un efecto secundario beneficioso: reduce la posibilidad de cometer errores. Si hubisemos escrito mal el procedimiento de lectura del valor entero positivo, bastara con corregir la funcin
correspondiente. Si en lugar de definir esa funcin hubisemos replicado el cdigo, nos tocara
corregir el mismo error en varios puntos del programa. Es fcil que, por descuido, olvidsemos corregir el error en uno de esos lugares y, sin embargo, penssemos que el problema est
solucionado.

6.7.2.

Mejora de la legibilidad

No solo nos ahorramos teclear: un programa que utiliza funciones es, por regla general, ms
legible que uno que inserta los procedimientos de clculo directamente donde se utilizan; bueno,
eso siempre que escojas nombres de funcin que describan bien qu hacen estas. Fjate en que el
ltimo programa es ms fcil de leer que el anterior, pues estas tres lneas son autoexplicativas:
1
2
3

a
b
c

6.7.3.

lee_entero_positivo
lee_entero_positivo
lee_entero_positivo

Algunos consejos para decidir qu debera definirse como funcin:


anlisis descendente y ascendente

Las funciones son un elemento fundamental de los programas. Ahora ya sabes cmo construir funciones, pero quiz no sepas cundo conviene construirlas. Lo cierto es que no podemos
decrtelo: no es una ciencia exacta, sino una habilidad que irs adquiriendo con la prctica. De
todos modos, s podemos darte algunos consejos.

1) Por una parte, todos los fragmentos de programa que vayas a utilizar en ms de una ocasin
son buenos candidatos a definirse como funciones, pues de ese modo evitars tener que
copiarlos en varios lugares. Evitar esas copias no solo resulta ms cmodo: tambin reduce
considerablemente la probabilidad de que cometas errores, pues acabas escribiendo menos
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

texto. Adems, si cometes errores y has de corregirlos o si has de modificar el programa


para ampliar su funcionalidad, siempre ser mejor que el mismo texto no aparezca en varios
lugares, sino una sola vez en una funcin.

2) Si un fragmento de programa lleva a cabo una accin que puedes nombrar o describir con una
sola frase, probablemente convenga convertirlo en una funcin. No olvides que los programas,
adems de funcionar correctamente, deben ser legibles. Lo ideal es que el programa conste
de una serie de definiciones de funcin y un programa principal breve que las use y resulte
muy legible.

3) No conviene que las funciones que definas sean muy largas. En general, una funcin debera
ocupar menos de 30 o 40 lneas (aunque siempre hay excepciones). Una funcin no solo
debera ser breve, adems debera hacer una nica cosa. . . y hacerla bien. Deberas ser
capaz de describir con una sola frase lo que hace cada una de tus funciones. Si una funcin
hace tantas cosas que explicarlas todas cuesta mucho, probablemente haras bien en dividir
tu funcin en funciones ms pequeas y simples. Recuerda que puedes llamar a una funcin
desde otra.
El proceso de identificar acciones complejas y dividirlas en acciones ms sencillas se conoce
como estrategia de diseo descendente (en ingls, top-down). La forma de proceder es esta:

analiza primero qu debe hacer tu programa y haz un esquema que explicite las diferentes
acciones que debe efectuar, pero sin entrar en el detalle de cmo debe efectuarse cada
una de ellas;
define una posible funcin por cada una de esas acciones;

analiza entonces cada una de esas acciones y mira si an son demasiado complejas; si es
as, aplica el mismo mtodo hasta que obtengas funciones ms pequeas y simples.

Una estrategia de diseo alternativa recibe el calificativo de ascendente (en ingls, bottomup) y consiste en lo contrario:
detecta algunas de las acciones ms simples que necesitars en tu programa y escribe
pequeas funciones que las implementen;
combina estas acciones en otras ms complejas y crea nuevas funciones para ellas;
sigue hasta llegar a una o unas pocas funciones que resuelven el problema.

Ahora que empiezas a programar resulta difcil que seas capaz de anticiparte y detectes
a simple vista qu pequeas funciones te irn haciendo falta y cmo combinarlas apropiadamente. Ser ms efectivo que empieces siguiendo la metodologa descendente: ve dividiendo
cada problema en subproblemas ms y ms sencillos que, al final, se combinarn para dar solucin al problema original. Cuando tengas mucha ms experiencia, probablemente descubrirs
que al programar sigues una estrategia hbrida, ascendente y descendente a la vez. Todo llega.
Paciencia.

6.8.

Recursin

Desde una funcin puedes llamar a otras funciones. Ya lo hemos hecho en los ejemplos que
hemos estudiado, pero qu ocurrira si una funcin llamara a otra y esta, a su vez, llamara a la
primera? O de modo ms inmediato, qu pasara si una funcin se llamara a s misma?
Una funcin que se llama a s misma, directa o indirectamente, es una funcin recursiva. La
recursin es un potente concepto con el que se pueden expresar ciertos procedimientos de clculo
muy elegantemente. No obstante, al principio cuesta un poco entender las funciones recursivas. . .
y un poco ms disear nuestras propias funciones recursivas. La recursin es un concepto difcil
cuando ests aprendiendo a programar. No te asustes si este material se te resiste ms que el
resto.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6.8.1.

Clculo recursivo del factorial

Empezaremos por presentar y estudiar una funcin recursiva: el clculo recursivo del factorial
de un nmero natural. Partiremos de la siguiente definicin matemtica, vlida para valores
positivos de n:

1,
si n = 0 o n = 1;
n! =
n (n 1)!, si n > 1.

Es una definicin de factorial un tanto curiosa: se define en trminos de s misma! El segundo


de sus dos casos dice que para conocer el factorial de n hay que conocer el factorial de n 1 y
multiplicarlo por n. Entonces, cmo calculamos el factorial de n 1? En principio, conociendo
antes el valor del factorial de n 2 y multiplicando ese valor por n 1. Y el de n 2? Pues
del mismo modo. . . y as hasta que acabemos por preguntarnos cunto vale el factorial de 1. En
ese momento no necesitaremos hacer ms clculos: el primer caso de la frmula nos dice que 1!
vale 1.
Vamos a plasmar esta idea en una funcin Python:
1
2
3
4
5
6

def factorial n
if n
0 or n
1
resultado
1
elif n
1
resultado
n
factorial n 1
return resultado

Compara la frmula matemtica y la funcin Python. No son tan diferentes. Python nos fuerza
a decir lo mismo de otro modo, es decir, con otra sintaxis. Ms all de las diferencias de forma,
ambas definiciones son idnticas.
Para entender la recursin, nada mejor que verla en funcionamiento. La figura 6.1 te muestra
paso a paso qu ocurre si solicitamos el clculo del factorial de 5. Estudia bien la figura. Con el
anidamiento de cada uno de los pasos pretendemos ilustrar que el clculo de cada uno de los
factoriales tiene lugar mientras el anterior an est pendiente de completarse. En el nivel ms
interno, factorial 5 est pendiente de que acabe factorial 4 , que a su vez est pendiente de
que acabe factorial 3 , que a su vez est pendiente de que acabe factorial 2 , que a su vez est
pendiente de que acabe factorial 1 . Cuando factorial 1 acaba, pasa el valor 1 a factorial 2 ,
que a su vez pasa el valor 2 a factorial 3 , que a su vez pasa el valor 6 a factorial 4 , que a
su vez pasa el valor 24 a factorial 5 , que a su vez devuelve el valor 120.
De acuerdo, la figura 6.1 describe con mucho detalle lo que ocurre, pero es difcil de seguir
y entender. Veamos si la figura 6.2 te es de ms ayuda. En esa figura tambin se describe paso
a paso lo que ocurre al calcular el factorial de 5, solo que con la ayuda de unos muecos.
En el paso 1, le encargamos a Amadeo que calcule el factorial de 5. l no sabe calcular
el factorial de 5, a menos que alguien le diga lo que vale el factorial de 4.
En el paso 2, Amadeo llama a un hermano clnico suyo, Benito, y le pide que calcule
el factorial de 4. Mientras Benito intenta resolver el problema, Amadeo se echa a dormir
(paso 3).
Benito tampoco sabe resolver directamente factoriales tan complicados, as que llama a
su clon Ceferino en el paso 4 y le pide que calcule el valor del factorial de 3. Mientras,
Benito se echa a dormir (paso 5).

La cosa sigue igual un ratillo: Ceferino llama al clon David y David a Eduardo. As llegamos
al paso 9 en el que Amadeo, Benito, Ceferino y David estn durmiendo y Eduardo se
pregunta cunto valdr el factorial de 1.
En el paso 10 vemos que Eduardo cae en la cuenta de que el factorial de 1 es muy fcil
de calcular: vale 1.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Empezamos invocando factorial(5). Se ejecuta, pues, la lnea 2 y como n no vale 0 o


1, pasamos a ejecutar la lnea 4. Como n es mayor que 1, pasamos ahora a la lnea 5.
Hemos de calcular el producto de n por algo cuyo valor es an desconocido: factorial(4).
El resultado de ese producto se almacenar en la variable local resultado, pero antes
hay que calcularlo, as que hemos de invocar a factorial(4).

Invocamos ahora factorial(4). Se ejecuta la lnea 2 y como n, que ahora vale 4, no vale 0 o 1,
pasamos a ejecutar la lnea 4. Como n es mayor que 1, pasamos ahora a la lnea 5. Hemos de
calcular el producto de n por algo cuyo valor es an desconocido: factorial(3). El resultado
de ese producto se almacenar en la variable local resultado, pero antes hay que calcularlo,
as que hemos de invocar a factorial(3).

Invocamos ahora factorial(3). Se ejecuta la lnea 2 y como n, que ahora vale 3, no vale 0 o 1, pasamos
a ejecutar la lnea 4, de la que pasamos a la lnea 5 por ser n mayor que 1. Hemos de calcular el
producto de n por algo cuyo valor es an desconocido: factorial(2). El resultado de ese producto se
almacenar en la variable local resultado, pero antes hay que calcularlo, as que hemos de invocar
a factorial(2).

Invocamos ahora factorial(2). Se ejecuta la lnea 2 y como n, que ahora vale 2, no es 0 o 1, pasamos a ejecutar
la lnea 4 y de ella a la 5 por satisfacerse la condicin de que n sea mayor que 1. Hemos de calcular el
producto de n por algo cuyo valor es an desconocido: factorial(1). El resultado de ese producto se almacenar
en la variable local resultado, pero antes hay que calcularlo, as que hemos de invocar a factorial(1).

Invocamos ahora factorial(1). Se ejecuta la lnea 2 y como n vale 1, pasamos a la lnea 3. En ella se dice que resultado vale 1, y en la lnea 6 se
devuelve ese valor como resultado de llamar a factorial(1).

Ahora que sabemos que el valor de factorial(1) es 1, lo multiplicamos por 2 y almacenamos el valor resultante,
2, en resultado. Al ejecutar la lnea 6, ese ser el valor devuelto.

Ahora que sabemos que el valor de factorial(2) es 2, lo multiplicamos por 3 y almacenamos el valor
resultante, 6, en resultado. Al ejecutar la lnea 6, ese ser el valor devuelto.

Ahora que sabemos que el valor de factorial(3) es 6, lo multiplicamos por 4 y almacenamos


el valor resultante, 24, en resultado. Al ejecutar la lnea 6, ese ser el valor devuelto.

Ahora que sabemos que el valor de factorial(4) es 24, lo multiplicamos por 5 y almacenamos el valor resultante, 120, en resultado. Al ejecutar la lnea 6, ese ser el valor
devuelto.
Figura 6.1: Traza del clculo recursivo de factorial(5).

En el paso 11 Eduardo despierta a David y le comunica lo que ha averiguado: el factorial


de 1! vale 1.

En el paso 12 Eduardo nos ha abandonado: l ya cumpli con su deber. Ahora es David


el que resuelve el problema que le haban encargado: 2! se puede calcular multiplicando
2 por lo que valga 1!, y Eduardo le dijo que 1! vale 1.
En el paso 13 David despierta a Ceferino para comunicarle que 2! vale 2. En el paso 14
Ceferino averigua que 3! vale 6, pues resulta de multiplicar 3 por el valor que David le ha
comunicado.
Y as sucesivamente hasta llegar al paso 17, momento en el que Benito despierta a Amadeo
y le dice que 4! vale 24.

En el paso 18 solo queda Amadeo y descubre que 5! vale 120, pues es el resultado de
multiplicar por 5 el valor de 4!, que segn Benito es 24.

Una forma compacta de representar la secuencia de llamadas es mediante el denominado


rbol de llamadas:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1)
5! = 5 4!
2)
3)
4)
5)
6)
7)
8)
9)

10)
11)

5! 4!

12)

5!

4! = 4 3!

5!

4! 3!

5!

4!

3! = 3 2!

5!

4!

3! 2!

5!

4!

3!

2! = 2 1!

5!

4!

3!

2! 1!

5!

4!

3!

2!

13)
14)
15)
16)

5!

4!

3!

2!

5!

4!

3!

2! 1! = 1

5!

4!

3!

2! = 2 1

5!

4!

3! 2! = 2

5!

4!

3! = 3 2

5!

4! 3! = 6

5!

4! = 4 6

17)
5! 4! = 24
1!

1! = 1

18)
5! = 5 24

Figura 6.2: Cmic explicativo del clculo recursivo del factorial de 5.


programa principal
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)

120
24
6
2
1

Los nodos del rbol de llamadas se visitan de arriba a abajo (flechas de trazo continuo) y
cuando se ha alcanzado el ltimo nodo, de abajo a arriba. Sobre las flechas de trazo discontinuo
hemos representado el valor devuelto por cada llamada.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Recurrir o iterar?

Hemos propuesto una solucin recursiva para el clculo del factorial, pero en anteriores apartados
hemos hecho ese mismo clculo con un mtodo iterativo. Esta funcin calcula el factorial iterativamente
(con un bucle for in):
1
2
3
4
5

def factorial n
f
1
for i in range 1 n 1
f
i
return f

Pues bien, para toda funcin recursiva podemos encontrar otra que haga el mismo clculo de
modo iterativo. Ocurre que no siempre es fcil hacer esa conversin o que, en ocasiones, la versin
recursiva es ms elegante y legible que la iterativa (o, cuando menos, se parece ms a la definicin
matemtica). Por otra parte, las versiones iterativas suelen ser ms eficientes que las recursivas, pues
cada llamada a una funcin supone pagar una pequea penalizacin en tiempo de clculo y espacio
de memoria, ya que se consume memoria y algo de tiempo en gestionar la pila de llamadas a funcin.

354

355
rales:

Haz una traza de la pila de llamadas a funcin paso a paso para factorial 5 .

Tambin podemos formular recursivamente la suma de los n primeros nmeros natun



i=1

i=

1,

n + n1
i=1 i,

si n = 1;
si n > 1.

Disea una funcin Python recursiva que calcule el sumatorio de los n primeros nmeros naturales.
356
calcule

Inspirndote en el ejercicio anterior, disea una funcin recursiva que, dados m y n,


n

i=m

i.

357
La siguiente funcin implementa recursivamente una comparacin entre dos nmeros
naturales. Qu comparacin?
1
2
3
4
5
6
7

def comparacin a b
if b
0
return False
elif a
0
return True
else
return comparacin a 1

6.8.2.

b 1

Clculo recursivo del nmero de bits necesarios para representar un


nmero

Vamos con otro ejemplo de recursin. Vamos a hacer un programa que determine el nmero
de bits necesarios para representar un nmero entero dado. Para pensar en trminos recursivos
hemos de actuar en dos pasos:
1) Encontrar uno o ms casos sencillos, tan sencillos que sus respectivas soluciones sean obvias.
A esos casos los llamaremos casos base.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Regresin infinita

Observa que una eleccin inapropiada de los casos base puede conducir a una recursin que no
se detiene jams. Es lo que se conoce por regresin infinita y es anloga a los bucles infinitos.
Por ejemplo, imagina que deseamos implementar el clculo recursivo del factorial y diseamos
esta funcin errnea:
1
2
3
4
5

def factorial n
if n
1
return 1
else
return n

factorial n 1

Qu ocurre si calculamos con ella el factorial de 0, que es 1? Se dispara una cadena infinita de
llamadas recursivas, pues el factorial de 0 llama a factorial de 1, que a su vez llama a factorial de
2, y as sucesivamente. Jams llegaremos al caso base.
De todos modos, el computador no se quedar colgado indefinidamente: el programa acabar
por provocar una excepcin. Por qu? Porque la pila de llamadas ir creciendo hasta ocupar toda
la memoria disponible, y entonces Python indicar que se produjo un desbordamiento de pila (en
ingls, stack overflow).

2) Plantear el caso general en trminos de un problema similar, pero ms sencillo. Si, por
ejemplo, la entrada del problema es un nmero, conviene que propongas una solucin en
trminos de un problema equivalente sobre un nmero ms pequeo.

En nuestro problema los casos base seran 0 y 1: los nmeros 0 y 1 necesitan un solo bit para
ser representados, sin que sea necesario hacer ningn clculo para averiguarlo. El caso general,
digamos n, puede plantearse del siguiente modo: el nmero n puede representarse con 1 bit ms
que el nmero n//2 (donde la divisin es entera). El clculo del nmero de bits necesarios para
representar n//2 parece ms sencillo que el del nmero de bits necesarios para representar n,
pues n//2 es ms pequeo que n.
Comprobemos que nuestro razonamiento es cierto. Cuntos bits hacen falta para representar
el nmero 5? Uno ms que los necesarios para representar el 2 (que es el resultado de dividir
5 entre 2 y quedarnos con la parte entera). Y para representar el nmero 2? Uno ms que los
necesarios para representar el 1. Y para representar el nmero 1?: fcil, ese es un caso base
cuya solucin es 1 bit. Volviendo hacia atrs queda claro que necesitamos 2 bits para representar
el nmero 2 y 3 bits para representar el nmero 5.
Ya estamos en condiciones de escribir la funcin recursiva:
1
2
3
4
5
6

def bits n
if n
0 or n
1
resultado
1
else
resultado
1
bits n
return resultado

358
bits 63 .

Dibuja un rbol de llamadas que muestre paso a paso lo que ocurre cuando calculas

359
Disea una funcin recursiva que calcule el nmero de dgitos que tiene un nmero
entero (en base 10).

6.8.3.

Los nmeros de Fibonacci

El ejemplo que vamos a estudiar ahora es el del clculo recursivo de nmeros de Fibonacci.
Los nmeros de Fibonacci son una secuencia de nmeros muy particular:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

F1
1

F2
1

F3
2

F4
3

F5
5

F6
8

F7
13

F8
21

F9
34

F10
55

F11
89

...
...

Los dos primeros nmeros de la secuencia valen 1 y cada nmero a partir del tercero se obtiene
sumando los dos anteriores. Podemos expresar esta definicin matemticamente as:

1,
si n = 1 o n = 2;
Fn =
Fn1 + Fn2 , si n > 2.
Los nmeros de Fibonacci en el mundo real

Los nmeros de Fibonacci son bastante curiosos, pues aparecen espontneamente en la naturaleza.
Te presentamos algunos ejemplos:

Las abejas comunes viven en colonias. En cada colonia hay una sola reina (hembra), muchas
trabajadoras (hembras estriles) y algunos znganos (machos). Los machos nacen de huevos no
fertilizados, por lo que tienen madre, pero no padre. Las hembras nacen de huevos fertilizados y,
por tanto, tienen padre y madre. Estudiemos el rbol genealgico de 1 zngano: tiene 1 madre,
2 abuelos (su madre tiene padre y madre), 3 bisabuelos, 5 tatarabuelos, 8 tatara-tatarabuelos,
13 tatara-tatara-tatarabuelos. . . Fjate en la secuencia: 1, 1, 2, 3, 5, 8, 13, . . . A partir del tercero,
cada nmero se obtiene sumando los dos anteriores. Esta secuencia es la serie de Fibonacci.
Muchas plantas tienen un nmero de ptalos que coincide con esa secuencia de nmeros: la
flor del iris tiene 3 ptalos, la de la rosa silvestre, 5 ptalos, la del dephinium, 8, la de la
cineraria, 13, la de la chicoria, 21, . . . Y as sucesivamente (las hay con 34, 55 y 89 ptalos).
El nmero de espirales cercanas al centro de un girasol que van hacia a la izquierda y las que
van hacia la derecha son, ambos, nmeros de la secuencia de Fibonacci.

Tambin el nmero de espirales que en ambos sentidos presenta la piel de las pias coincide
con sendos nmeros de Fibonacci.

Podramos dar an ms ejemplos. Los nmeros de Fibonacci aparecen por doquier. Y adems, son tan
interesantes desde un punto de vista matemtico que hay una asociacin dedicada a su estudio que
edita trimestralmente una revista especializada con el ttulo The Fibonacci Quarterly.

1
2
3
4
5
6

La transcripcin de esta definicin a una funcin Python es fcil:

def fibonacci n
if n
1 or n
2
resultado
1
elif n
2
resultado
fibonacci n 1
return resultado

fibonacci n 2

Ahora bien, entender cmo funciona fibonacci en la prctica puede resultar un tanto ms
dficil, pues el clculo de un nmero de Fibonacci necesita conocer el resultado de dos clculos
adicionales (salvo en los casos base, claro est). Vemoslo con un pequeo ejemplo: el clculo
de fibonacci 4 .

Llamamos a fibonacci 4 . Como n no vale ni 1 ni 2, hemos de llamar a fibonacci 3 y a


fibonacci 2 para, una vez devueltos sus respectivos valores, sumarlos. Pero no se ejecutan
ambas llamadas simultneamente. Primero se llama a uno (a fibonacci 3 ) y luego al otro
(a fibonacci 2 ).
Llamamos primero a fibonacci 3 . Como n no vale ni 1 ni 2, hemos de llamar a
fibonacci 2 y a fibonacci 1 para, una vez recibidos los valores que devuelven,
sumarlos. Primero se llama a fibonacci 2 , y luego a fibonacci 1 .

Llamamos primero a fibonacci 2 . Este es fcil: devuelve el valor 1.


Llamamos a continuacin a fibonacci 1 . Este tambin es fcil: devuelve el valor
1.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ahora que sabemos que fibonacci 2 devuelve un 1 y que fibonacci 1 devuelve un


1, sumamos ambos valores y devolvemos un 2. (Recuerda que estamos ejecutando una
llamada a fibonacci 3 ).

Y ahora llamamos a fibonacci 2 , que inmediatamente devuelve un 1.

Ahora que sabemos que fibonacci 3 devuelve un 2 y que fibonacci 2 devuelve un 1,


sumamos ambos valores y devolvemos un 3. (Recuerda que estamos ejecutando una llamada
a fibonacci 4 ).

He aqu el rbol de llamadas para el clculo de fibonacci 4 :


programa principal
3

fibonacci(4)
fibonacci(3)

fibonacci(2)

fibonacci(2)

fibonacci(1)

En qu orden se visitan los nodos del rbol? El orden de visita se indica en la siguiente
figura con los nmeros rodeados por un crculo.
programa principal

1
2
3
360
361

fibonacci(3)

fibonacci(2)

fibonacci(4)
2
1

fibonacci(2)

fibonacci(1)

Calcula F12 con ayuda de la funcin que hemos definido.


Dibuja el rbol de llamadas para fibonacci 5 .

362
Modifica la funcin para que, cada vez que se la llame, muestre por pantalla un men, donde n es el valor del argumento, y
saje que diga
para que, justo antes de acabar, muestre por pantalla
, donde m es el valor a devolver. A continuacin, llama a la funcin
para calcular el cuarto nmero de Fibonacci y analiza el texto que aparece por pantalla. Haz lo
mismo para el dcimo nmero de Fibonacci.
363

Puedes calcular recursivamente los nmeros combinatorios sabiendo que, para n m,


  
 

n
n1
n1
=
+
m
m
m1

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Programas eficientes o algoritmos eficientes?

Hemos presentado un programa recursivo para el clculo de nmeros de Fibonacci. Todo programa
recursivo puede reescribirse con iteraciones. He aqu una versin iterativa:
1
2
3
4
5
6
7
8

def fibonacci_iterativo n
if n
1 or n
2
f
1
else
f1
f2
1
for i in range 3 n 1
f f1 f2
f1
return f

f2

f2

La funcin iterativa es muchsimo ms rpida que la recursiva. La mayor rapidez no se debe a


que haya menos llamadas a funcin, sino al propio algoritmo utilizado. El algoritmo recursivo que
hemos diseado tiene un coste exponencial, mientras que el iterativo tiene un coste lineal. Que qu
significa eso? Pues que el nmero de pasos del algoritmo lineal es directamente proporcional al
valor de n, mientras que crece brutalmente en el caso del algoritmo recursivo: cada llamada a funcin
genera (hasta) dos nuevas llamadas a funcin que, a su vez, generarn (hasta) otras dos cada una, y
as sucesivamente. El nmero total de llamadas crece al mismo ritmo que 2n . . . una funcin que crece
vertiginosamente con n. Entonces, un algoritmo iterativo es siempre preferible a uno recursivo? No.
No siempre hay una diferencia de costes tan alta. En este caso, no obstante, podemos estar satisfechos
del programa iterativo, al menos si lo comparamos con el recursivo. Conviene usarlo siempre? No.
El algoritmo iterativo no es el ms eficiente de cuantos se conocen para el clculo de nmeros de
Fibonacci. Hay una frmula no recursiva que conduce a un algoritmo ms eficiente:

n 
n 
1
1 5
1+ 5
Fn =

2
2
5

Si defines una funcin que implemente ese clculo, vers que es mucho ms rpida que la funcin
iterativa. Moraleja: la clave de un programa eficiente se encuentra (casi siempre) en disear (o
encontrar en la literatura!) un algoritmo eficiente. Los libros de algortmica son una excelente fuente
de soluciones ya diseadas por otros o, cuando menos, de buenas ideas aplicadas a otros problemas
que nos ayudan a disear mejores soluciones para los nuestros. En un tema posterior estudiaremos
la cuestin de la eficiencia de los algoritmos.

y que

   
n
n
= 1.
=
0
n

 
Disea un programa que, a partir de un valor n ledo de teclado, muestre mn para m entre 0
y n. El programa llamar a una funcin combinaciones definida recursivamente.

364
El nmero
  de formas diferentes de dividir un conjunto de n nmeros en k subconjuntos
se denota con nk y se puede definir recursivamente as:
n

n
k

n1
k 1

+k

n1
k

n
El valor de 1 , al igualque
el
de
n , es 1. Disea un programa que, a partir de un valor n

n
ledo de teclado, muestre m para m entre 0 y n. El programa llamar a una funcin particiones
definida recursivamente.

6.8.4.

El algoritmo de Euclides

Veamos otro ejemplo. Vamos a calcular el mximo comn divisor (mcd) de dos nmeros n y m
por un procedimiento conocido como algoritmo de Euclides, un mtodo que se conoce desde la
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

antigedad y que se suele considerar el primer algoritmo propuesto por el hombre. El algoritmo
dice as:
Calcula el resto de dividir el mayor de los dos nmeros por el menor de ellos. Si
el resto es cero, entonces el mximo comn divisor es el menor de ambos nmeros.
Si el resto es distinto de cero, el mximo comn divisor de n y m es el mximo
comn divisor de otro par de nmeros: el formado por el menor de n y m y por dicho
resto.

Resolvamos un ejemplo a mano. Calculemos el mcd de 500 y 218 paso a paso:

1) Queremos calcular el mcd de 500 y 218. Empezamos calculando el resto de dividir 500 entre
218: es 64. Como el resto no es cero, an no hemos terminado. Hemos de calcular el mcd de
218 (el menor de 500 y 218) y 64 (el resto de la divisin).
2) Ahora queremos calcular el mcd de 218 y 64, pues ese valor ser tambin la solucin al
problema original. El resto de dividir 218 entre 64 es 26, que no es cero. Hemos de calcular
el mcd de 64 y 26.

3) Ahora queremos calcular el mcd de 64 y 26, pues ese valor ser tambin la solucin al
problema original. El resto de dividir 64 entre 26 es 12, que no es cero. Hemos de calcular
el mcd de 26 y 12.

4) Ahora queremos calcular el mcd de 26 y 12, pues ese valor ser tambin la solucin al
problema original. El resto de dividir 26 entre 12 es 2, que no es cero. Hemos de calcular el
mcd de 12 y 2.

5) Ahora queremos calcular el mcd de 12 y 2, pues ese valor ser tambin la solucin al problema
original. El resto de dividir 12 entre 2 es 0. Por fin: el resto es nulo. El mcd de 12 y 2, que
es el mcd de 26 y 12, que es el mcd de 64 y 26, que es el mcd de 218 y 64, que es el mcd
de 500 y 218, es 2.

En el ejemplo desarrollado se hace explcito que una y otra vez resolvemos el mismo problema,
solo que con datos diferentes. Si analizamos el algoritmo en trminos de recursin encontramos
que el caso base es aquel en el que el resto de la divisin es 0, y el caso general, cualquier
otro.
Necesitaremos calcular el mnimo y el mximo de dos nmeros, por lo que nos vendr bien
definir antes funciones que hagan esos clculos4 . Aqu tenemos el programa que soluciona
recursivamente el problema:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18

def min a b
if a
b
return a
else
return b
def max a b
if a
b
return a
else
return b

def mcd m n
menor
min m n
mayor
max m n
resto
mayor
menor
if resto
0
return menor

4 Fjate: estamos aplicando la estrategia de diseo ascendente. Antes de saber qu haremos exactamente, ya estamos
definiendo pequeas funciones auxiliares que, seguro, nos interesar tener definidas.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

else

19
20

return mcd menor

resto

He aqu el rbol de llamadas para el clculo de mcd 500 128 :


programa principal
2

mcd(500, 218)
min(500, 218)

500

218
max(500, 218)
min(218, 64)

2
mcd(218, 64)

218

64
max(218, 64)
min(64, 26)

2
mcd(64, 26)

64

26
max(64, 26)
min(26, 12)

2
mcd(26, 12)

26

12
max(26, 12)

mcd(12, 2)
min(12, 2)

365
366

12

max(12, 2)

Haz una traza de las llamadas a mcd para los nmeros 1470 y 693.
Haz una traza de las llamadas a mcd para los nmeros 323 y 323.

367
En el apartado 6.6.4 presentamos el mtodo de la biseccin. Observa que, en el fondo,
se trata de un mtodo recursivo. Disea una funcin que implemente el mtodo de la biseccin
recursivamente.

6.8.5.

Las torres de Hanoi

Cuenta la leyenda que en un templo de Hanoi, bajo la cpula que seala el centro del mundo,
hay una bandeja de bronce con tres largas agujas. Al crear el mundo, Dios coloc en una de
ellas sesenta y cuatro discos de oro, cada uno de ellos ms pequeo que el anterior hasta llegar
al de la cima. Da y noche, incesantemente, los monjes transfieren discos de una aguja a otra
siguiendo las inmutables leyes de Dios, que dicen que debe moverse cada vez el disco superior
de los ensartados en una aguja a otra y que bajo l no puede haber un disco de menor radio.
Cuando los sesenta y cuatro discos pasen de la primera aguja a otra, todos los creyentes se
convertirn en polvo y el mundo desaparecer con un estallido5 .
Nuestro objetivo es ayudar a los monjes con un ordenador. Entendamos bien el problema
resolviendo a mano el juego para una torre de cuatro discos. La situacin inicial es esta.

Y deseamos pasar a esta otra situacin:

5 La leyenda fue inventada por De Parville en 1884, en Mathematical Recreations and Essays, un libro de pasatiempos matemticos. La ambientacin era diferente: el templo estaba en Benars y el dios era Brahma.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Aunque solo podemos tocar el disco superior de un montn, pensemos en el disco del fondo.
Ese disco debe pasar de la primera aguja a la tercera, y para que eso sea posible, hemos de
conseguir alcanzar esta configuracin:

Solo en ese caso podemos pasar el disco ms grande a la tercera aguja, es decir, alcanzar
esta configuracin:

Est claro que el disco ms grande no se va a mover ya de esa aguja, pues es su destino
final. Cmo hemos pasado los tres discos superiores a la segunda aguja? Mmmm. Piensa que
pasar una pila de tres discos de una aguja a otra no es ms que el problema de las torres de
Hanoi para una torre de tres discos. Qu nos faltar por hacer? Mover la pila de tres discos
de la segunda aguja a la tercera, y eso, nuevamente, es el problema de la torres de Hanoi para
tres discos. Ves cmo aparece la recursin? Resolver el problema de las torres de Hanoi con
cuatro discos requiere:
resolver el problema de las torres de Hanoi con tres discos, aunque pasndolos de la aguja
inicial a la aguja libre;
mover el cuarto disco de la aguja en que estaba inicialmente a la aguja de destino;

y resolver el problema de las torres de Hanoi con los tres discos que estn en la aguja
central, que deben pasar a la aguja de destino.

La verdad es que falta cierta informacin en la solucin que hemos esbozado: deberamos indicar
de qu aguja a qu aguja movemos los discos en cada paso. Reformulemos, pues, la solucin y
hagmosla general formulndola para n discos y llamando a las agujas inicial, libre y final (que
originalmente son las agujas primera, segunda y tercera, respectivamente):
Resolver el problema de la torres de Hanoi con n discos que hemos de transferir de la aguja
inicial a la aguja final requiere:
resolver el problema de las torres de Hanoi con n 1 discos de la aguja inicial a la aguja
libre,
mover el ltimo disco de la aguja inicial a la aguja de destino,

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

y resolver el problema de las torres de Hanoi con n 1 discos de la aguja libre a la aguja
final.

Hay un caso trivial o caso base: el problema de la torres de Hanoi para un solo disco (basta
con mover el disco de la aguja en la que est insertado a la aguja final). Ya tenemos, pues, los
elementos necesarios para resolver recursivamente el problema.
Qu parmetros necesita nuestra funcin? Al menos necesita el nmero de discos que vamos
a mover, la aguja origen y la aguja destino. Identificaremos cada aguja con un nmero. Esbocemos
una primera solucin:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

def resuelve_hanoi n inicial final


if n
1
print
inicial
else
Determinar cul es la aguja libre
if inicial
1 and final
1
libre
1
elif inicial
2 and final
2
libre
2
else
libre
3
Primer subproblema: mover n-1 discos de inicial a libre
resuelve_hanoi n 1 inicial libre
Transferir el disco grande a su posicin final
print
inicial
Segundo subproblema: mover n-1 discos de libre a final
resuelve_hanoi n 1 libre final

final

final

Para resolver el problema con n = 4 invocaremos resuelve_hanoi 4 1 3 .


Podemos presentar una versin ms elegante que permite suprimir el bloque de lneas 511
aadiendo un tercer parmetro.
1
2
3
4
5
6
7
8
9

def resuelve_hanoi n inicial final libre


if n
1
print
else
resuelve_hanoi n 1 inicial libre final
print
resuelve_hanoi n 1 libre final inicial
resuelve_hanoi 4 1 3 2

inicial
inicial

final
final

El tercer parmetro se usa para pasar el dato de qu aguja est libre, y no tener que
calcularla cada vez. Ahora, para resolver el problema con n = 4 invocaremos resuelve_hanoi 4
1 3 2 . Si lo hacemos, por pantalla aparece:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ejecutemos las rdenes que imprime resuelve_hanoi:


1

10

11

12

13

14

15

16

368
Es hora de echar una manita a los monjes. Ellos han de resolver el problema con 64
discos. Por qu no pruebas a ejecutar resuelve_hanoi 64 1 3 2 ?

369
Cuntos movimientos son necesarios para resolver el problema de las torres de
Hanoi con 1 disco, y con 2, y con 3, . . . ? Disea una funcin movimientos_hanoi que reciba un
nmero y devuelva el nmero de movimientos necesarios para resolver el problema de la torres
de Hanoi con ese nmero de discos.
370
Implementa un programa grfico con tortuga que muestre grficamente la resolucin
del problema de las torres de Hanoi.
371

6.8.6.

Dibuja el rbol de llamadas para resuelve_hanoi 4

Recursin indirecta

2 .

Las recursiones que hemos estudiado hasta el momento reciben el nombre de recursiones
directas, pues una funcin se llama a s misma. Es posible efectuar recursin indirectamente:
una funcin puede llamar a otra quien, a su vez, acabe llamando a la primera.
Estudiemos un ejemplo sencillo, meramente ilustrativo de la idea y, la verdad, poco til.
Podemos decidir si un nmero natural es par o impar siguiendo los siguientes principios de
recursin indirecta:
un nmero n es par si n 1 es impar,
un nmero n es impar si n 1 es par.
0 es par.

1
2
3
4
5
6
7
8
9

10
11

Podemos implementar en Python las funciones par e impar as:

def par n
if n
0
return True
else
return impar n 1
def impar n
if n
0
return False
else
return par n 1

Fjate en que el rbol de llamadas de par 4 alterna llamadas a par e impar:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

programa principal
par(4)

True
True

impar(3)
par(2)

True
True

impar(1)
par(0)

6.8.7.

True

Grficos fractales: copos de nieve de Von Koch

En 1904, Helge von Koch present en un trabajo cientfico una curiosa curva que da lugar
a unos grficos que hoy se conocen como copos de nieve de Von Koch. La curva de Von Koch
se define recursivamente y es tanto ms compleja cuanto ms profunda es la recursin. He aqu
algunos ejemplos de curvas de Von Koch con niveles de recursin crecientes:
1

El arte de la recursin

La recursin no es un concepto de exclusiva aplicacin en matemticas o programacin. Tambin


el mundo de la literatura, el cine o el diseo han explotado la recursin. El libro de Las mil y una
noches, por ejemplo, es un relato que incluye relatos que, a su vez, incluyen relatos. Numerosas
pelculas incluyen en su trama el rodaje o el visionado de otras pelculas: Cantando bajo la lluvia,
de Stanley Donen y Gene Kelly, Nickelodeon, de Peter Bogdanovich, o Vivir rodando, de Tom
DiCillo, son pelculas en las que se filman otras pelculas; en Angustia, de Bigas Luna, somos
espectadores de una pelcula en la que hay espectadores viendo otra pelcula. Maurits Cornelius
Escher es autor de numerosos grabados en los que est presente la recursin, si bien normalmente
con regresiones infinitas. En su grabado Manos dibujando, por ejemplo, una mano dibuja a otra que,
a su vez, dibuja a la primera (una recursin indirecta).
El libro Gdel, Escher, Bach: un Eterno y Grcil Bucle, de Douglas R. Hofstadter, es un apasionante ensayo sobre esta y otras cuestiones.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Los copos de nieve de Von Koch se forman combinando tres curvas de Von Koch que unen los
vrtices de un tringulo equiltero. Aqu tienes cuatro copos de nieve de Von Koch para niveles
de recursin 0, 1, 2 y 3, respectivamente:

Estos grficos reciben el nombre de copos de nieve de Von Koch porque recuerdan los
diseos de cristalizacin del agua cuando forma copos de nieve.
Veamos cmo dibujar copos de nieve de Von Koch. Hemos de pensar en trminos de la
tortuga, que es la herramienta con la que dibujamos. Una curva de Koch viene descrita por dos
elementos: la longitud y el nivel. Pensemos en la curva de Koch ms sencilla: la de nivel cero y
una longitud cualquiera. Esa curva es muy sencilla de trazar: es una simple lnea de la longitud
especificada. Vayamos ahora a por la curva de nivel 1 y longitud arbitraria. Esa curva se divide
en 4 segmentos. El primero recorre una distancia de l/3, donde l es la longitud especificada;
gira entonces 60 grados a la izquierda, avanza l/3, gira 120 grados a la derecha, avanza l/3, gira
otros 60 grados a la izquierda y, finalmente, avanza una distancia l/3.
El procedimiento conduce a un mtodo recursivo si reparamos en un importante detalle: cada
uno de los 4 tramos que componen una curva de Koch de nivel 1 son, a su vez, curvas de Koch
de nivel 0 (pues son simples lneas rectas). Esa es la clave. La curva de Koch de nivel n se forma
con cuatro curvas de Koch de nivel n 1, cada una de las cuales se dibuja a partir de un giro
apropiado a derecha o izquierda. Esta implementacin refleja esa idea:
He aqu una implementacin del algoritmo:
1
2
3
4
5
6
7
8
9

10
11

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19

def koch tortuga longitud nivel


if nivel
0
tortuga forward longitud
else
koch tortuga longitud 3
tortuga left 60
koch tortuga longitud 3
tortuga right 120
koch tortuga longitud 3
tortuga left 60
koch tortuga longitud 3

nivel 1
nivel 1
nivel 1
nivel 1

Para tener un programa operativo necesitaremos un programa principal:

from turtle import Screen

Turtle

def koch tortuga longitud nivel


if nivel
0
tortuga forward longitud
else
koch tortuga longitud 3
tortuga left 60
koch tortuga longitud 3
tortuga right 120
koch tortuga longitud 3
tortuga left 60
koch tortuga longitud 3
pantalla
Screen
pantalla setup 500 500
pantalla screensize 500 500
pantalla setworldcoordinates 0
tortuga
Turtle

nivel 1
nivel 1
nivel 1
nivel 1
250

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

500

250

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

20
21
22

tortuga speed 9
koch tortuga 400 5
pantalla exitonclick

El copo de Koch se obtiene uniendo tres curvas de Koch, cada una de las cuales est girada
120 grados a la derecha con respecto a la anterior. Esta funcin recibe como datos el tamao
de los segmentos principales y el nivel de recursin:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

from turtle import Screen

Turtle

def koch tortuga longitud nivel


if nivel
0
tortuga forward longitud
else
koch tortuga longitud 3
tortuga left 60
koch tortuga longitud 3
tortuga right 120
koch tortuga longitud 3
tortuga left 60
koch tortuga longitud 3
def copo tortuga
koch tortuga
tortuga right
koch tortuga
tortuga right
koch tortuga

longitud
longitud
120
longitud
120
longitud

nivel
nivel

nivel 1
nivel 1
nivel 1
nivel 1

nivel
nivel

pantalla
Screen
pantalla setup 500 500
pantalla screensize 500 500
pantalla setworldcoordinates 0
tortuga
Turtle
tortuga speed 9
copo tortuga 400 3
pantalla exitonclick

350

500

150

Aqu tienes el resultado de ejecutar la funcin con diferentes niveles de recursin (0, 1, 3 y
4, respectivamente):

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

372
Puedes jugar con los diferentes parmetros que determinan la curva de Koch para
obtener infinidad de figuras diferentes. Basta con controlar los ngulos de giro y las longitudes
apropiadamente:
1
2
3
4
5
6
7
8
9

10
11

1
2
3
4
5
6
7
8
9

10
11

def koch tortuga longitud nivel


if nivel
0
tortuga forward longitud
else
koch tortuga longitud 3
tortuga left 80
koch tortuga longitud 3
tortuga right 160
koch tortuga longitud 3
tortuga left 80
koch tortuga longitud 3

def koch tortuga longitud nivel


if nivel
0
tortuga forward longitud
else
koch tortuga longitud 3
tortuga left 40
koch tortuga longitud 4
tortuga right 160
koch tortuga longitud 6
tortuga left 120
koch tortuga longitud 5

nivel 1
nivel 1
nivel 1
nivel 1

nivel 1
nivel 1
nivel 1
nivel 1

Prueba a cambiar los diferentes parmetros y trata de predecir la figura que obtendrs en cada
caso antes de ejecutar el programa.

373
Estas dos funciones, mutuamente recursivas, definen otra estructura fractal interesante: la denominada curva dragn:
1

def dragon tortuga

longitud

nivel

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19

if nivel
tortuga
else
tortuga
dragon
tortuga
nogard
tortuga

0
forward longitud

right 45
tortuga longitud sqrt 2
left 90
tortuga longitud sqrt 2
right 45

def nogard tortuga longitud nivel


if nivel
0
tortuga forward longitud
else
tortuga left 45
dragon tortuga longitud sqrt 2
tortuga right 90
nogard tortuga longitud sqrt 2
tortuga left 45

nivel 1

nivel 1

nivel 1

nivel 1

Trata de entender el principio de dibujo de este tipo de curva fractal. Aqu tienes las curvas
dragn de niveles 2, 3, 4, 5 y 6.

El perfil de la curvas dragn tiene una analoga con las dobleces de una hoja de papel. La
curva dragn de nivel 0 es el perfil de una hoja de papel que no ha sido doblada. La de nivel 1
ha sido doblada una vez y desdoblada hasta que las partes dobladas forman ngulos de 90
grados. La curva dragn de nivel 2 es el perfil de una hoja doblada dos veces y desdoblada de
forma que cada parte forme un ngulo de 90 grados con la siguiente.
Por cierto, de dnde viene el nombre de curva dragn? Del aspecto que presenta en
niveles grandes. Aqu tienes la curva dragn de nivel 11:

374
Otra figura recursiva que es todo un clsico es la criba o tringulo de Sierpinski. En
cada nivel de recursin se divide cada uno de los tringulos del nivel anterior en tres nuevos
tringulos. Esta figura muestra los tringulos de Sierpinski para niveles de recursin de 0 a 4:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Disea un programa que dibuje tringulos de Sierpinski para un nivel de recursin dado.

375
Otra curva fractal de inters es la denominada curva de relleno del espacio de
Hilbert. Esta figura te muestra dicha curva con niveles de recursin 0, 1, 2, 3 y 4:

Disea un programa capaz de dibujar curvas de relleno del espacio de Hilbert dado el nivel
de recursin deseado. Estas figuras te pueden ser de ayuda para descubrir el procedimiento de
clculo que has de programar:

376
Una curiosa aplicacin de la recursin es la generacin de paisajes por ordenador. Las
montaas, por ejemplo, se dibujan con modelos recursivos: los denominados fractales (las curvas
de Von Koch, entre otras, son fractales). Los rboles pueden generarse tambin con procedimientos
recursivos. Estas imgenes, por ejemplo, muestran esqueletos de rboles generados con Python:

Todos han sido generados con una misma funcin recursiva, pero usando diferentes argumentos.
Te vamos a describir el principio bsico de generacin de estos rboles, pero has de ser t mismo
quien disee una funcin recursiva capaz de efectuar este tipo de dibujos. Vamos con el mtodo.
El usuario nos proporciona los siguientes datos:
Los puntos en los que empieza y acaba el tronco.

El ngulo que forma la rama que parte a mano derecha del tronco con el propio tronco.
La rama que parte a mano izquierda lo hace con un ngulo .
La proporcin (en tanto por uno) del tamao de las ramas con respecto al tronco.
El nivel de recursin deseado.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

La recursin tiene lugar cuando consideramos que cada una de las dos ramas es un nuevo tronco.
Por cierto, los rboles ganan bastante si en los primeros niveles de recursin usas un color
anaranjado o marrn y en los ltimos usas un color verde.

377
Los rboles que hemos generado en el ejercicio anterior parecen un tanto artificiales
por ser tan regulares y simtricos. Introducir el azar en su diseo los har parecer ms naturales.
Modifica la funcin del ejercicio anterior para que tanto el ngulo como la proporcin rama/tronco
se escojan aleatoriamente (dentro de ciertos mrgenes).
Aqu tienes un par de ejemplos. El rbol de la izquierda s parece bastante real y el de la
derecha parece mecido por el viento (bueno, ms bien por un huracn!).

6.9.

Mdulos

6.9.1.

Un mdulo muy sencillo: mnimo y mximo

Las funciones ayudan a hacer ms legibles tus programas y a evitar que escribas una y otra
vez los mismos clculos en un mismo programa. Sin embargo, cuando escribas varios programas,
posiblemente descubrirs que acabas escribiendo la misma funcin en cada programa. . . a menos
que escribas tus propios mdulos.
Los mdulos son colecciones de funciones que puedes utilizar desde tus programas. Conviene
que las funciones se agrupen en mdulos segn su mbito de aplicacin.
La distribucin estndar de Python nos ofrece gran nmero de mdulos predefinidos. Cada
mdulo agrupa las funciones de un mbito de aplicacin. Las funciones matemticas se agrupan
en el mdulo math; las que analizan documentos HTML (el lenguaje de marcas del World Wide
Web) en htmllib; las que generan nmeros al azar, en random; las que trabajan con fechas de
calendario, en calendar; las que permiten montar un cliente propio de FTP (un protocolo de
intercambio de ficheros en redes de ordenadores), en ftplib. . . Como ves, Python tiene una gran
coleccin de mdulos predefinidos. Conocer aquellos que guardan relacin con las reas de
trabajo para las que vas a desarrollar programas te convertir en un programador ms eficiente:
para qu volver a escribir funciones que ya han sido escritas por otros?6
En esta seccin aprenderemos a crear y usar nuestros propios mdulos. As, podremos reutilizar funciones que ya hemos escrito al solucionar un problema de programacin: para qu
volver a escribir funciones que ya han sido escritas por nosotros mismos?7
Empezaremos creando un mdulo con las funciones min y max que definimos en un ejemplo
anterior. Llamaremos al mdulo minmax, as que deberemos crear un fichero de texto llamado
. El sufijo o extensin
sirve para indicar que el fichero contiene cdigo Python.
Este es el contenido del fichero:
1

def min a

6 Bueno,
7 Bueno,

si ests aprendiendo a programar, s tiene algn sentido.


si ests aprendiendo a programar, s tiene algn sentido.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

if a

2
3

else

4
5
6
7
8
9

10
11

b
return a
return b

def max a b
if a
b
return a
else
return b

En cualquier programa donde deseemos utilizar las funciones min y max bastar con incluir
antes la siguiente lnea:
1

from minmax import min

max

Observa que escribimos from minmax, y no from


forma parte del nombre del mdulo.

: la extensin del fichero no

378
Construye un mdulo llamado dni que incluya las funciones de clculo de la letra
del DNI.
Usa el mdulo desde un programa que pida al usuario su nmero de DNI y su letra. Si el
.
usuario mete un nmero y letra de DNI correctos, el programa emitir el mensaje
.
En caso contrario dir
y

Cuando importas por primera vez el mdulo


, Python crea automticamente un fichero
llamado
. Ese fichero contiene una versin de tu mdulo ms fcil de cargar en memoria
para Python, pero absolutamente ilegible para las personas: est codificado en lo que llamamos
formato binario. Python pretende acelerar as la carga de mdulos que usas en tus programas, pero
sin obligarte a ti a gestionar los ficheros
.
Si borras el fichero
, no pasar nada grave: sencillamente, Python lo volver a crear
cuando cargues nuevamente el mdulo
desde un programa cualquiera. Si modificas el
contenido de
, Python regenera automticamente el fichero
para que siempre
est sincronizado con
.

6.9.2.

Un mdulo ms interesante: gravedad

En un mdulo no solo puede haber funciones: tambin puedes definir variables cuyo valor
debe estar predefinido. Por ejemplo, el mdulo matemtico (math) incluye constantes como pi o
e que almacenan (sendas aproximaciones a) el valor de y e, respectivamente. Para definir una
variable en un mdulo basta con incluir una asignacin en el fichero de texto.
Vamos con un nuevo ejemplo: un mdulo con funciones y constantes fsicas relacionadas con
la gravitacin. Pero antes, un pequeo repaso de fsica.
La fuerza (en Newtons) con que se atraen dos cuerpos de masa M y m (en kilogramos)
separados una distancia r (en metros) es
F =G

Mm
,
r2

donde G es la denominada constante de gravitacin universal. G vale, aproximadamente, 6.67


1011 N m2 kg2 . Por otra parte, la velocidad de escape de un planeta para un cuerpo cualquiera
es

2GM
,
ve =
R
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Probando los mdulos

Una vez has escrito un mdulo es buena prctica probar que funciona correctamente. Puedes crear
un programa que utilice a tu mdulo en muchas circunstancias diferentes para ver que proporciona los
resultados correctos. En ese caso tendrs dos ficheros de texto: el fichero que corresponde al mdulo
en s y el que contiene el programa de pruebas. Python te permite que el contenido de ambos ficheros
resida en uno solo: el del mdulo.
El siguiente texto reside en un nico fichero (
):
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

def min a b
if a
b
return a
else
return b
def max a b
if a
b
return a
else
return b
if __name__
print
print
print
print

max
max
min
min

3 10
3 10
3 10
3 10

Si lo que hacemos es importar el mdulo minmax desde otro fichero, as:

from minmax import min

max

, que es como se llama el mdulo. De este modo podemos saber


la variable __name__ vale
si el cdigo del fichero se est ejecutando o importando. Pues bien, el truco est en ejecutar la batera
de pruebas solo cuando el fichero se est ejecutando.

Mximo y mnimo

Ya te hemos comentado que Python trae muchas utilidades de fbrica. Las funciones de clculo
del mximo y el mnimo parecen muy tiles, as que sera de extraar que no estuvieran predefinidas.
Pues bien, lo estn: la funcin max calcula el mximo y min el mnimo. Fjate:

Las funciones max y min funcionan con cualquier nmero de argumentos mayor que cero. Recuerdas los ejercicios en que te pedamos calcular el mayor (o menor) de 5 nmeros? Entonces s
que te hubiera venido bien saber que existan max (o min)!
Estas funciones tambin trabajan con listas:

Lo cierto es que max y min funcionan con cualquier tipo de secuencia. Una curiosidad: qu crees
que devolver max
? Y min
?

donde M es la masa del planeta (en kilogramos) y R su radio (en metros).


Nuestro mdulo, al que denominaremos gravedad, exportar unas cuantas constantes:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

G: la constante de gravitacin universal.


MTierra: la masa de la Tierra.
RTierra: el radio de la Tierra.

veTierra: la velocidad de escape de la Tierra.


MLuna: la masa de la Luna.
RLuna: el radio de la Luna.

veLuna: la velocidad de escape de la Luna.

Por cierto, la masa de la Tierra es de 5.97 1024 kilogramos y su radio es de 6.37 106 metros;
y la masa de la Luna es de 7.35 1022 kilogramos y su radio es de 1.74 106 metros.
Por otra parte, el mdulo definir las siguientes funciones:

fuerzaGravitatoria: recibe la masa de dos cuerpos (en kilogramos) y la distancia que los
separa (en metros) y devuelve la fuerza gravitatoria que experimentan (en Newtons).

distancia: recibe la masa de dos cuerpos (en kilogramos) y la fuerza gravitatoria que
experimentan por efecto mutuo (en Newtons) y devuelve la distancia que los separa (en
metros).
velocidadEscape: recibe la masa (en kilogramos) y el radio (en metros) de un planeta y
devuelve la velocidad (en metros por segundo) que permite a un cuerpo cualquiera escapar
de la rbita del planeta.

He aqu (una primera versin de) el contenido del fichero


debe finalizar con la extensin ):
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19

(recuerda que el fichero

from math import sqrt


G
6.67e 11
MTierra
5.97e24
RTierra
6.37e6
MLuna
7.35e22
RLuna
1.74e6

def fuerzaGravitatoria M m r
return G
M
m
r 2
def distancia M m
return sqrt G

F
M

def velocidadEscape M
return sqrt 2
G
veTierra
veLuna

R
M

velocidadEscape MTierra RTierra


velocidadEscape MLuna RLuna

Observa que las variables veTierra y veLuna se han definido al final (lneas 18 y 19). Lo
hemos hecho as para poder aprovechar la funcin velocidadEscape, que ha de estar definida
antes de ser usada (lneas 1516). Por otra parte, el mdulo utiliza una funcin (sqrt) del mdulo
matemtico, as que empieza importndola (lnea 1).
Acabaremos mostrando un ejemplo de uso del mdulo gravedad desde un programa (que
estar escrito en otro fichero de texto):
1

from gravedad import velocidadEscape

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

veTierra

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

2
3
4
5

print
print
print

6.10.

velocidadEscape 1.29e22 1.16e6


veTierra

end

Documentacin del cdigo

Ya empezamos a crear programas de cierta entidad. Y solo estamos aprendiendo a programar!


Cuando trabajes con programas del mundo real, vers que estos se dividen en numerosos mdulos y, generalmente, cada uno de ellos define muchas funciones y constantes. Esos programas, por
regla general, no son obra de un solo programador, sino de un equipo de programadores. Muchas
veces, el autor o autores de un mdulo necesitan consultar mdulos escritos por otros autores, o a
un programador se le puede encargar que siga desarrollando un mdulo de otros programadores,
o que modifique un mdulo que l mismo escribi hace mucho tiempo. Es vital, pues, que los
programas sean legibles y estn bien documentados.
Hemos de acostumbrarnos a documentar el cdigo. Nuestro mdulo estar incompleto sin
una buena documentacin:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

Mdulo: gravedad

Propsito: proporciona algunas constantes y funciones sobre fsica gravitatoria.

Autor/es: Isaac Prez Gonzlez y Alberto Prez Lpez

Constantes exportadas:
G: Constante de gravitacin universal.
MTierra: Masa de la Tierra (en kilos).
RTierra: Radio de la Tierra (en metros).
MLuna: Masa de la Luna (en kilos).
RLuna: Radio de la Luna (en metros).

Funciones exportadas:
fuerzaGravitatoria: calcula la fuerza gravitatoria existente entre dos cuerpos.
entradas:
M: masa de un cuerpo (en kg).
m: masa del otro cuerpo (en kg).
r: distancia entre ellos (en metros).
salida:
fuerza (en Newtons).

distancia: calcula la distancia que separa dos cuerpos atrados por una fuerza
gravitatoria determinada.
entradas:
M: masa de un cuerpo (en kg).
m: masa del otro cuerpo (en kg).
F: fuerza gravitatoria experimentada (en m).
salida:
distancia (en metros).

velocidadEscape: calcula la velocidad necesaria para escapar de la atraccin


gravitatoria de un cuerpo esfrico.
entradas:
M: masa del cuerpo (en kg).
R: radio del cuerpo (en metros).
salida:
velocidad (en metros por segundo).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

Historia:
* Creado el 13/11/2001 por Isaac
* Modificado el 15/11/2001 por Alberto:
- se incluyen las constantes MLuna y RLuna
- se aade la funcin velocidadEscape

from math import sqrt


G
6.67e 11
MTierra
5.97e24
RTierra
6.37e6
MLuna
7.35e22
RLuna
1.74e6

def fuerzaGravitatoria M m r
return G
M
m
r 2
def distancia M m
return sqrt G

F
M

def velocidadEscape M
return sqrt 2
G
veTierra
veLuna

R
M

velocidadEscape MTierra RTierra


velocidadEscape MLuna RLuna

De acuerdo, el mdulo es ahora mucho ms largo, pero est bien documentado. Cualquiera
puede averiguar su utilidad con solo leer la cabecera.
ndate con ojo: no todos los comentarios son interesantes. Este, por ejemplo, es absurdo:
1
2

Devuelve el producto de G por M y m dividido por r al cuadrado.


return G
M
m
r
2

Lo que dice ese comentario es una obviedad. En este caso, el comentario no ayuda a entender
nada que no est ya dicho en la propia sentencia. Ms que ayudar, distrae al lector. La prctica
te har ir mejorando el estilo de tus comentarios y te ayudar a decidir cundo convienen y
cundo son un estorbo.

379
Disea un mdulo que agrupe las funciones relacionadas con hipotecas de los ejercicios 304307. Documenta adecuadamente el mdulo.

6.10.1.

Otro mdulo: clculo vectorial

Vamos a desarrollar ahora un mdulo para clculo vectorial en tres dimensiones. Un vector tridimensional (x, y, z) se representar mediante una lista con tres elementos numricos:
x y z . Nuestro mdulo suministrar funciones y constantes tiles para el clculo con este
tipo de datos.
Empezaremos definiendo una a una las funciones y constantes que ofrecer nuestro mdulo.
Despus mostraremos el mdulo completo.
Definamos una funcin que sume dos vectores. Primero hemos de tener claro cmo se define
matemticamente la suma de vectores: (x, y, z) + (x  , y , z  ) = (x + x  , y + y , z + z  ). Llamaremos
vSuma a la operacin de suma de vectores:
1
2

def vSuma u v
return
u 0

v 0

u 1

v 1

La longitud de un vector (x, y, z) es

def vLongitud v

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

u 2

v 2

x 2 + y2 + z 2 . Definamos una funcin vLongitud:

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

return sqrt v 0

v 1

v 2

u 2

v 2

Recuerda que antes deberemos importar sqrt del mdulo math.


El producto escalar de dos vectores (x, y, z) y (x  , y , z  ) es una cantidad escalar igual a

xx + yy + zz  :
1
2

def vProductoEscalar u v
return u 0 v 0
u 1

v 1

Dos vectores son perpendiculares si su producto escalar es cero. Construyamos una funcin
que devuelva True cuando dos vectores son perpendiculares y False en caso contrario:
1
2

def vSonPerpendiculares u v
return vProductoEscalar u v

El producto vectorial de dos vectores (x, y, z) y (x  , y , z  ) se define como un nuevo vector


(yz zy , zx  xz  , xy yx  ):
1
2
3
4
5

def vProductoVectorial u v
resultado_x
u 1 v 2
u 2 v 1
resultado_y
u 2 v 0
u 0 v 2
resultado_z
u 0 v 1
u 1 v 0
return resultado_x resultado_y resultado_z

Para facilitar la introduccin de vectores, vamos a definir una funcin vLeeVector que lea de
teclado las tres componentes de un vector:
1
2
3
4
5

def vLeeVector
x
float input
y
float input
z
float input
return x y z

Y para facilitar la impresin de vectores, definiremos un procedimiento que muestra un vector por pantalla siguiendo la notacin habitual en matemticas (con parntesis en lugar de
corchetes):
1
2

def vMuestraVector v
print

format v 0

v 1

v 2

Los vectores i = (1, 0, 0), j = (0, 1, 0) y k = (0, 0, 1) se definirn en nuestro mdulo como las
variables vI, vJ y vK, respectivamente.
1
2
3

vI
vJ
vK

1 0 0
0 1 0
0 0 1

Bueno, es hora de juntarlo todo en un mdulo. En un fichero llamado vectores py tecleamos


el siguiente texto:
1
2
3
4
5
6
7
8

Mdulo vectores

Proporciona constantes y funciones para el clculo vectorial en 3 dimensiones.

Constantes que exporta:


vI, vJ, vK: vectores unidad

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

Funciones que exporta:


vLeeVector:
sin parmetros
devuelve un vector ledo de teclado que se pide al usuario
vMuestraVector(v):
muestra por pantalla el vector v con la notacin(x,y,z)
no devuelve nada
vLongitud()v):
devuelve la longitud del vector v

vSuma(u, v):
devuelve el vector resultante de sumar u y v

vProductoEscalar(u, v):
devuelve el escalar resultante del producto escalar de u por v

vProductorVectorial()u, v):
devuelve el vector resultante del producto vectorial de u por v

vSonPerpendiculares(u, v):
devuelve cierto si u y v son perpendiculares, y falso en caso contrario

Funciones matemticas utilizadas

from math import sqrt


Constantes

vI
vJ
vK

1 0 0
0 1 0
0 0 1

Funciones de entrada/salida

def vLeeVector
x
float input
y
float input
z
float input
return x y z

def vMuestraVector v
print

Funciones de clculo

def vLongitud v
return sqrt v 0
def vSuma u v
return
u 0

format v 0
2

v 0

v 1

u 1

def vProductoEscalar u v
return u 0 v 0
u 1
def vProductoVectorial u v
resultado_x
u 1 v 2
resultado_y
u 2 v 0
resultado_z
u 0 v 1

v 1

v 2

v 1

u 2
u 0
u 1

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

u 2

v 1
v 2
v 0

v 1
2

u 2

v 2

v 2

v 2

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

70
71
72
73
74
75

return

resultado_x

Predicados

resultado_y

def vSonPerpendiculares u v
return vProductoEscalar u v

resultado_z
0

380
Disea un mdulo similar al anterior pero que permita efectuar clculos con vectores
n-dimensionales, donde n es un valor arbitrario. Las funciones que debes definir son:
vLeeVector: Pide el valor de n y a continuacin lee los n componentes del vector. El
resultado devuelto es la lista de los componentes.
vMuestraVector: Muestra por pantalla el vector en la notacin (v1 , v2 , . . . , vn ).
vLongitud: devuelve la longitud del vector, que es

 n


v2
i=1

vSuma: Devuelve la suma de dos vectores. Los dos vectores deben tener la misma dimensin.
Si no la tienen, vSuma devolver el valor None.

vProductoEscalar: Devuelve el producto escalar de dos vectores. Los dos vectores deben
tener la misma dimensin. Si no la tienen, la funcin devolver el valor None.

381
Disea un mdulo que facilite el trabajo con conjuntos. Recuerda que un conjunto es
una lista en la que no hay elementos repetidos. Debers implementar las siguientes funciones:

lista_a_conjunto lista : Devuelve un conjunto con los mismos elementos que hay en lista,
pero sin repeticiones. (Ejemplo: lista_a_conjunto 1 1 3 2 3 devolver la lista 1 2
3 , aunque tambin se acepta como equivalente cualquier permutacin de esos mismos
elementos, como 3 1 2 o 3 2 1 ).
unin A

B : devuelve el conjunto resultante de unir los conjuntos A y B.

interseccin A
diferencia A

B : devuelve el conjunto cuyos elementos pertenecen a A y a B.

B : devuelve el conjunto de elementos que pertenecen a A y no a B.

iguales A B : devuelve cierto si A y B tienen los mismos elementos y falso en caso


contrario. (Nota: ten en cuenta que los conjuntos representados por las listas 1 3 2
y 2 1 3 son iguales).

6.10.2.

Un mdulo para trabajar con polinomios

Supn que deseamos trabajar con polinomios, es decir, con funciones de la forma
f (x) = a0 + a1 x + a2 x 2 + a3 x 3 + + an x n .

Nos interesar poder operar con polinomios. Disearemos un mdulo que permita:

Mostrar por pantalla los polinomios en una notacin similar a la matemtica.


Evaluar un polinomio para un valor dado de x.

Obtener el polinomio que resulta de sumar otros dos.


Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Obtener el polinomio que resulta de restar un polinomio a otro.

Obtener el polinomio que resulta de multiplicar dos polinomios.

Empezaremos por decidir una representacin para los polinomios. Un polinomio de orden n
es una lista de n + 1 elementos: los n + 1 coeficientes del polinomio. El polinomio
1 + 2x + 4x 2 5x 3 + 6x 5

es de orden 5, as que se representar con una lista de 6 elementos: 1 2 4


5 0 6 .
Ahora que hemos decidido la representacin que usaremos, hagamos un procedimiento que
muestre por pantalla un polinomio en un formato agradable y no como una lista de nmeros:
1
2
3
4
5

1
2
3
4
5

def muestra p
print p 0
end
for i in range 1 len p
print
p i
print

end

Diseemos la funcin que evale un polinomio p para un valor dado de x:

def evala p x
suma
0
for i in range len p
suma
suma
p i
return suma

Vamos a por la funcin que suma dos polinomios. Antes de empezar, entendamos qu hay que
hacer. Supongamos que hemos de sumar los polinomios a0 +a1 x+ +an x n y b0 +b1 x+ +bn x n .
Fcil: la solucin es un polinomio c0 + c1 x + + cn x n donde ci = ai + bi , para i entre 0 y n.
Bueno, este caso era particularmente fcil porque ambos polinomios eran del mismo orden. Si
los polinomios sumados son de rdenes distintos deberemos llevar ms cuidado.
Lo que no va a funcionar es el operador , pues al trabajar con listas efecta una concatena1 , que representan polinomios
cin. Es decir, si concatenamos las listas 1 2 3 y 1 0
de orden 2, obtenemos un polinomio de orden 5 (el representado por la lista 1 2 3 1 0
1 ), y eso es incorrecto.
Vamos con una propuesta de funcin suma:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15

1
2
3
4

def suma a b
creamos un polinomio nulo de orden igual al de mayor orden
c
0
max len a
len b
sumamos los coeficientes hasta el orden menor
for i in range min len a
len b
c i
a i
b i
y ahora copiamos el resto de coeficientes del polinomio de mayor orden.
if len a
len b
for i in range len b
len c
c i
a i
else
for i in range len a
len c
c i
b i
y devolvemos el polinomio c
return c

382

Es correcta esta otra versin de la funcin suma?

def suma a b
c
m
min len a
len b
for i in range m

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

5
6
7

c append a i
b i
c
c
a m
b m
return c

Ya casi est. Hay un pequeo detalle: imagina que sumamos los polinomios representados
3 . El polinomio resultante es 2 4 0 . Bien, pero ese polinomio
por 1 2 3 y 1 2
es un poco anormal: parece de orden 2, pero en realidad es de orden 1, ya que el ltimo
coeficiente, el que afecta a x 2 es nulo. Diseemos una funcin que normalice los polinomios
eliminando los coeficientes nulos a la derecha del todo:
1
2
3

def normaliza p
while len p
del p 1

0 and p

Nuestra funcin suma (y cualquier otra que opere con polinomios) deber asegurarse de que
devuelve un polinomio normalizado:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15

16

def suma a b
creamos un polinomio nulo de orden igual al de mayor orden
c
0
max len a
len b
sumamos los coeficientes hasta el orden menor
for i in range min len a
len b
c i
a i
b i
y ahora copiamos el resto de coeficientes del polinomio de mayor orden.
if len a
len b
for i in range len b
len c
c i
a i
else
for i in range len a
len c
c i
b i
normalizamos y devolvemos el polinomio c
normaliza c
return c

La funcin que resta un polinomio de otro te la dejamos como ejercicio. Vamos con el producto
de polinomios, que es una funcin bastante ms complicada. Si multiplicamos dos polinomios a y
b de rdenes n y m, respectivamente, el polinomio resultante c es de orden n + m. El coeficiente
de orden ci se obtiene as:
Vamos con la funcin:
1
2
3
4
5
6
7
8
9

ci =

i

j=0

aj bij .

def multiplica a b
orden
len a
len b
2
c
0
orden
1
for i in range orden 1
suma
0
for j in range i 1
suma
a j
b i j
c i
suma
return c

Encrgate t ahora de unir las funciones desarrolladas en un mdulo llamado polinomios.

383
Disea el siguiente programa que usa el mdulo polinomios y, si te parece conveniente, enriquece dicho mdulo con nuevas funciones tiles para el manejo de polinomios. El
programa presentar al usuario este men:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6.10.3.

Un mdulo con utilidades estadsticas

Vamos a ilustrar lo aprendido con el desarrollo de un mdulo interesante: una coleccin de


funciones que permitan realizar estadsticas de series de nmeros, concretamente, el clculo
de la media, de la varianza y de la desviacin tpica.
Nuestro mdulo debera utilizarse desde programas como se ilustra en este ejemplo:
1
2
3
4
5
6
7
8
9

10

from estadisticas import media


notas
nota
float input
while nota
0 and nota
notas append nota
nota
float input
print
print

media notas

desviacin_tpica

10
desviacin_tpica notas

La media de una serie de nmeros a1 , a2 , . . . , an es


1
=
ai ,
a
n
n

su varianza es
y su desviacin tpica es

1
2
3
4
5

1
2
3
4

i=1

2 =

1
)2 .
(ai a
n
n

i=1



n
1 
)2 .
=
(ai a
n

Empecemos por el clculo de la media:

i=1

def media lista


suma
0
for elemento in lista
suma
elemento
return suma
len lista

La varianza utiliza el valor de la media y podemos obtenerlo llamando a media:

def varianza lista


suma
0
for elemento in lista
suma
elemento

media lista

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

return suma

len lista

Mmmm. Est bien, pero se efecta una llamada a media por cada iteracin del bucle y hay
tantas como elementos tiene la lista. Esa es una fuente de ineficiencia. Mejor calcular la media
una sola vez y guardarla en una variable local:
1
2
3
4
5

1
2

def varianza lista


suma
0
m
media lista
for elemento in lista
suma
elemento
return suma
len lista

Finalmente, la desviacin tpica no es ms que la raz cuadrada de la varianza, as que:

def desviacin_tpica lista


return sqrt varianza lista

384
Funcionan bien las funciones que hemos definido cuando suministramos listas vacas? Corrige las funciones para que traten correctamente este caso particular.

385
Enriquece el mdulo estadisticas aadiendo una funcin que calcule el coeficiente
de variacin (definido como /
a) y el recorrido de la lista (que es la diferencia entre el mayor
y el menor elemento de la lista).

386
Suponiendo que nos suministran una lista de enteros, disea una funcin que calcule
su moda. La moda es el elemento ms repetido en una serie de valores.

6.10.4.

Un mdulo para clculo matricial

En el tema anterior estudiamos cmo operar con matrices. Vamos a empaquetar ahora
algunas funciones tiles para manejar matrices.
Empezaremos por una funcin que crea una matriz nula dados su nmero de filas y columnas:
1
2
3
4
5

1
2
3
4
5
6

def matriz_nula filas columnas


M
for i in range filas
M append
0
columnas
return M

Para crear una matriz A de dimensin 3 4 invocaremos as a la funcin:

matriz_nula 3

Ahora podemos escribir una funcin que lee de teclado los componentes de una matriz:

def lee_matriz filas columnas


M
matriz_nula filas columnas
for i in range filas
for j in range columnas
M i j
float input
return M

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

format i

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Vamos ahora a por una funcin que sume dos matrices. Dos matrices A y B se pueden sumar
si presentan la misma dimensin, es decir, el mismo nmero de filas y el mismo nmero de
columnas. Nuestra funcin debera empezar comprobando este extremo. Cmo podemos conocer
la dimensin de una matriz M? El nmero de filas est claro: len M . Y el nmero de columnas?
Fcil, es el nmero de elementos de la primera fila (de cualquier fila, de hecho): len M 0 .
Expresar el nmero de filas y columnas como len M y len M 0 no ayudar a hacer legible
nuestra funcin de suma de matrices. Antes de empezar a escribirla, definamos una funcin que
devuelva la dimensin de una matriz:
1
2

def dimensin M
return len M

len M 0

Para averiguar el nmero de filas y columnas de una matriz A bastar con hacer:
filas

columnas

dimensin A

387
Disea una funcin llamada es_cuadrada que devuelva True si la matriz es cuadrada
(tiene igual nmero de filas que columnas) y False en caso contrario. Srvete de la funcin
dimensin para averiguar la dimensin de la matriz.

Ahora, nuestra funcin de suma de matrices empezar comprobando que las matrices que se
le suministran son compatibles. Si no lo son, devolveremos None (ausencia de valor):
1
2
3
4
5

def suma A B
if dimensin A
return None
else

dimensin B

Utilizaremos ahora la funcin matriz_nula para inicializar a cero la matriz resultante de


la suma y efectuamos el clculo (si tienes dudas acerca del procedimiento, consulta el tema
anterior):
1
2
3
4
5
6
7
8
9

10

def suma A B
if dimensin A
dimensin B
return None
else
m n
dimensin A
C
crea_matriz_nula m n
for i in range m
for j in range n
C i j
A i j
B i
return C

388
Enriquece el mdulo
con una funcin que devuelva el producto de dos
matrices. Si las matrices no son multiplicables, la funcin devolver None.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Captulo 7

Tipos estructurados: clases y


diccionarios

No tendra un sabor muy bueno, me temo. . .


Solo no le interrumpi con cierta impaciencia el Caballero pero no puedes imaginarte qu diferencia si lo mezclas con otras cosas. . .

Alicia en el pas de las maravillas, Lewis Carroll

El conjunto de tipos de datos Python que hemos estudiado se divide en tipos escalares
(enteros y flotantes) y tipos secuenciales (cadenas y listas). En este captulo aprenderemos a
definir y utilizar tipos de datos definidos por nosotros mismos componiendo otros tipos de datos
ms sencillos. Los nuevos tipos de datos reciben el nombre de clases.
Por otra parte, los diccionarios permiten mantener correspondencias entre claves y valores,
facilitando as la escritura de ciertos programas.

7.1.

7.1.1.

Tipos de datos a medida


Lo que sabemos hacer

Supn que en un programa utilizamos el nombre, el DNI y la edad de dos personas. Necesitaremos tres variables para almacenar los datos de cada persona, dos variables con valores de
tipo cadena (el nombre y el DNI) y otra con un valor de tipo entero (la edad):
1
2
3
4
5
6
7

nombre
dni
edad
19

otro_nombre
otro_dni
otra_edad
18

Los datos almacenados en nombre, dni y edad corresponden a la primera persona y los datos
guardados en otro_nombre, otro_dni y otra_edad corresponden a la segunda persona, pero nada
en el programa permite deducir eso con seguridad: cada dato est almacenado en una variable
diferente e independiente de las dems. El programador debe saber en todo momento qu
variables estn relacionadas entre s y en qu sentido para utilizarlas coherentemente.
Diseemos un procedimiento que muestre por pantalla los datos de una persona y usmoslo:
1
2
3
4
5

def imprimir_persona_en_pantalla nombre


print
nombre
print
dni
print
edad

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

dni

edad

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6
7

imprimir_persona_en_pantalla nombre dni edad


imprimir_persona_en_pantalla otro_nombre otro_dni

otra_edad

Al ejecutar ese fragmento de programa, por pantalla aparecer:

Funciona, pero resulta un tanto incmodo pasar tres parmetros cada vez que usamos el procedimiento. Si ms adelante enriquecemos los datos de una persona aadiendo su domicilio, por
ejemplo, tendremos que redefinir el procedimiento imprimir_persona_en_pantalla y cambiar todas sus llamadas para incluir el nuevo dato. En un programa de tamao moderadamente grande
puede haber decenas o cientos de llamadas a la funcin.
Imaginemos ahora que nuestro programa gestiona la relacin de personas que asiste a
clase. No sabemos a priori de cuntas personas estamos hablando, as que hemos de gestionar
una lista a la que iremos aadiendo cuantas personas sea necesario. Bueno, una lista no, sino tres
listas paralelas: una para los nombres, una para los DNI y una para las edades. Entenderemos
que los elementos de las tres listas que tienen el mismo ndice contienen los tres datos que
describen a una persona en nuestro programa. Este fragmento de cdigo ilustra la idea:
1
2
3
4
5
6

nombre
dni
edad

19

18

18

for i in range len nombre


imprimir_persona_en_pantalla nombre i

dni i

edad i

El bucle recorre con i los ndices 0, 1 y 2 y, para cada uno, muestra los tres datos asociados
a una de las personas. Por ejemplo, cuando i vale 1 se muestran los datos de Pedro Lpez,
que estn almacenados en nombre 1 , dni 1 y edad 1 . Hemos ganado en comodidad (ya no
hay que inventar un nombre de variable para cada dato de cada persona), pero hemos de estar
atentos y mantener la coherencia entre las tres listas. Si, por ejemplo, queremos borrar los datos
de Pedro Lpez, tendremos que ejecutar tres operaciones de borrado (del):
1
2
3

del nombre 1
del dni 1
del edad 1

Y si deseamos ordenar alfabticamente la relacin de personas por su nombre deberemos ser


cuidadosos: cada intercambio de elementos de la lista nombre, supondr el intercambio de los
elementos correspondientes en las otras dos listas.
En resumen, es posible desarrollar programas que gestionan personas con esta metodologa, pero resulta incmodo.

7.1.2.

. . . pero sabemos hacerlo mejor

Hay una alternativa a trabajar con grupos de tres variables independientes por persona: definir
una persona como una lista con tres elementos. En cada elemento de la lista almacenaremos
uno de sus valores, siempre en el mismo orden:
1
2

juan
pedro

19

18

Trabajar as permite que los datos de cada persona estn agrupados, s, pero tambin hace algo
incmodo su uso. Deberemos recordar que el ndice 0 accede al nombre, el ndice 1 al DNI y
el ndice 2 a la edad. Por ejemplo, para acceder a la edad de Juan Prez hemos de escribir
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

juan 2 . Es probable que cometamos algn error difcil de detectar si utilizamos los ndices
errneamente. Podramos facilitar el trabajo almacenando los ndices en unas variables cuyos
identificadores permitan recordar sus respectivos significados:
1
2
3
4
5
6

nombre
0
dni
1
edad
2
juan
pedro

19

18

Ahora, la edad de Juan Prez se puede obtener escribiendo juan edad , que es bastante ms
elegante que juan 2 . La funcin que muestra por pantalla todos los datos de una persona
tendra este aspecto:
1
2
3
4

def imprimir_persona_en_pantalla persona


print
persona nombre
print
persona dni
print
persona edad

Este procedimiento solo tiene un parmetro, as que, si aadimos nuevos datos a una persona,
solo modificaremos el cuerpo del procedimiento, pero no todas y cada una de sus llamadas.
Hemos mejorado, pues, con respecto a la solucin desarrollada en el apartado anterior.
Siguiendo esta filosofa, tambin es posible tener listas de personas, que no sern ms que
listas de listas:
1
2
3
4

juan
pedro

personas

juan

pedro

19

18

Continuar

Seguro que a estas alturas ya te has encontrado con numerosas ocasiones en las que no te cabe una
lnea de programa Python en el ancho normal de la pantalla. No te preocupes: puedes partir una lnea
Python en varias para aumentar la legibilidad, aunque debers indicarlo explcitamente. Una lnea que
finaliza con una barra invertida contina en la siguiente:
1
2

2
2

Ojo! La lnea debe acabar en barra invertida, es decir, el carcter que sigue a la barra invertida
debe ser el salto de lnea (que es invisible). Si a la barra invertida le sigue un espacio en blanco,
Python sealar un error.

O, directamente:
1
2

personas

19
18

(Si te sorprende la barra invertida al final de la primera lnea, lee el cuadro Continuar).
El nombre de Pedro Lpez, por ejemplo, est accesible en personas 1 nombre . Si deseamos
mostrar el contenido completo de la lista podemos hacer:
1
2

for persona in personas


imprimir_persona_en_pantalla persona

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Solucionado. Bueno, no del todo. Si trabajamos con esta metodologa nos aguardan nuevos
problemas. Imagina que nuestro programa gestiona informacin sobre personas y coches y que
de los coches necesitamos los siguientes datos: marca, modelo, matrcula y edad.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15

ndices para personas


nombre
0
dni
1
edad
2
juan
pedro

19
18

ndices para coches


modelo
0
marca
1
matrcula
2
edad
3
Mal: edad ya estaba definida antes y vala 2
mi_coche

42

La variable edad ya estaba ocupada por personas y vala 2, as que asignarle ahora un
valor distinto provocar errores cuando accedamos a la edad de una persona. Cmo hacemos
ahora para que la edad de un coche no se confunda con la edad de una persona? Tendremos
que optar por:

definir una nueva variable con otro nombre, por ejemplo, edad_coche, en la que almacenamos el ndice correspondiente (el valor 3),
o almacenar la edad del coche en la posicin de ndice 2 de la lista de datos del coche
(es decir, poner la matrcula en la ltima posicin de la lista y la edad en la penltima).

Cualquiera de las dos posibilidades es antinatural, pues estamos siendo obligados a tomar
decisiones acerca de cmo representar una informacin (coche) motivadas por la existencia de
otro tipo de informacin (persona) que nada tiene que ver con la primera. No es una buena
solucin.

7.1.3.

Lo que haremos: usar tipos de datos a medida

Lo ideal sera que Python proporcionara un tipo de datos bsico persona del mismo modo
que proporciona datos enteros, flotantes, listas, etc. Una variable cuyo contenido fuera de tipo
persona albergara en un solo paquete toda la informacin propia de una persona: su nombre,
su dni y su edad. Pero, claro, pronto pediremos que Python disponga de un tipo de datos coche
(con la marca, el modelo, la matrcula y la edad, por ejemplo), de un tipo de datos empleado
(con el nombre, nmina, categora profesional y direccin de una persona), de un tipo de datos
profesor (con su nombre, DNI, asignaturas impartidas y horarios de tutoras), etc., es decir,
pediremos que Python incorpore un tipo de datos para cada conjunto de datos hipotticamente
necesario en nuestros programas.
Python no puede anticiparse a cualquier necesidad de cualquier programador proporcionando
infinitos tipos de datos, pero s nos permite definir nuevos tipos de datos combinando tipos de
datos existentes.
Podemos definir un tipo de datos nuevo, digamos Persona, que agrupe en un solo paquete
los datos bsicos que lo forman: el nombre (una cadena), el DNI (otra cadena) y la edad (un
entero). Fjate en que el nuevo tipo de datos es una composicin de tipos de datos existentes.
Los nuevos tipos de datos recibirn el nombre genrico de clases.
Definir nuevos tipos de datos nos obligar a aprender nuevas construcciones sintcticas del
lenguaje Python, pero antes ser mejor que veamos con algunos ejemplos cmo se usarn los
nuevos tipos. Supongamos que hemos definido la clase Persona. Crearemos nuevas personas
as:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2

juan
Persona
pedro
Persona

19

18

Si necesitamos acceder al nombre, DNI o edad de Juan Prez, podremos hacerlo as:

Fjate: la variable juan contiene un dato de tipo Persona que, en realidad, son tres datos (el
nombre, el DNI y la edad). Cada uno de dichos datos recibe el nombre de atributo o campo.
Puedes consultar el valor de cada campo por su nombre separndolo del identificador de la
variable con un punto.
El nuevo tipo de datos sabr mostrarse en pantalla con la funcin print:

Mucho mejor que definir una funcin imprime_persona_en_pantalla!


Y an ms. Por ejemplo, imagina que necesitamos consultar con cierta frecuencia las iniciales
de una persona. Podremos definir una funcin especial que efecte el clculo correspondiente a
partir del nombre de la persona:
Observa que iniciales se usa casi como si fuera el nombre de un campo de juan, pues se
separa del identificador de la variable con un punto, pero se diferencia en el uso de parntesis
al final del identificador. Los parntesis indican que iniciales es una funcin especial, un mtodo
que forma parte del tipo Persona y que lo estamos llamando (del mismo modo que se llama a
una funcin). De todos modos, el uso de iniciales no debera resultarte demasiado extrao pues
ya hemos usado mtodos antes: al aadir un dato a una lista escribamos lista append dato ,
es decir, llambamos sobre lista al mtodo append con el dato que desebamos aadir.
Para acabar esta exposicin introductoria abordaremos el caso de la relacin de estudiantes
que asisten a clase y que antes resolvimos usando tres listas paralelas. Al disponer ahora de un
tipo de datos Persona solo es necesario disponer de una lista:
1
2
3

alumnos

Persona
Persona
Persona

19
18

20

El siguiente fragmento de cdigo mostrar los datos de todas las personas de la lista:
1
2

for i in range len alumnos


print alumnos i

O, alternativamente:
1
2

for alumno in alumnos


print alumno

Elegante, no?

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7.2.

Definicin de clases en Python

Vamos a definir un nuevo tipo de datos Python: la clase Persona. Presta atencin a la sintaxis:
es un poco enrevesada a primera vista.
1
2
3
4
5

class Persona
def __init__ self nombre dni
self nombre
nombre
self dni
dni
self edad
edad

edad

Analicmosla por partes. La primera lnea empieza con la palabra reservada class y con ella
indicamos que comienza la definicin de un nuevo tipo de datos, de una nueva clase. A continuacin aparece el identificador del nuevo tipo (Persona) y dos puntos. Las lneas 2 y siguientes
empiezan ms a la derecha y definen una funcin (empieza por def) llamada __init__. Las funciones que definimos dentro de una clase se denominan mtodos. El mtodo __init__ tiene cuatro
parmetros: el primero se llama self. Todos los mtodos tendrn como primer parmetro uno
llamado self. Le siguen tantos parmetros como campos tiene una variable del tipo Persona.1 El
cuerpo del mtodo __init__ (lneas 3 a 5) consiste en una serie de asignaciones de la forma:
Qu es self ? En ingls, self significa uno mismo. Al asignar a self nombre el valor del parmetro nombre estamos diciendo algo as como el nombre de uno mismo es el valor del parmetro
nombre. Es la forma de almacenar informacin en uno mismo.
Ya puedes almacenar personas en variables. Cada vez que quieras crear una nueva persona,
debers hacerlo as:
1

toni

Persona

20

Cada vez que creas o construyes una nueva persona, Python llama automticamente al mtodo
__init__. El mtodo __init__ es el denominado constructor de la clase Persona. Python interpreta
esa sentencia como:
1
2
3

toni nombre
toni dni
toni edad
20

pues self equivale a toni en el ejemplo.


Cada persona creada es una instancia u objeto de la clase Persona. Puedes utilizar objetos
de la clase Persona del mismo modo que utilizabas valores de otros tipos. Por ejemplo, puedes
crear personas y almacenarlas en variables y/o en listas, a voluntad:
1
2
3
4

toni
Persona
juan
Persona
pedro
Persona
alumnos
toni juan

pedro

19

20

18

Si deseas acceder a la edad de toni, podrs utilizar la notacin introducida en el apartado


anterior:
Puedes acceder a los elementos de la lista alumnos como siempre. Este fragmento de programa, por ejemplo, muestra el dni de los integrantes de la lista:
1 Ms

adelante veremos que no es necesario que haya tantos parmetros como atributos.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

POO

Este apartado constituye una introduccin a uno de los aspectos bsicos de la Programacin
Orientada a Objetos (POO). La POO es un paradigma (una forma) de programar muy extendida en
las ltimas dcadas. Los otros dos pilares de la POO son la herencia y el polimorfismo, aunque no
los trataremos en este curso.
Python es un lenguaje orientado a objetos, es decir, da soporte a las caractersticas propias de la
POO. Entre los lenguajes orientados a objetos de uso ms extendido se cuentan C++ y Java.
1
2

for alumno in alumnos


print alumno dni

Alternativamente puedes recorrer la lista as:


1
2

for i in range len alumnos


print alumnos i dni

Observa que en este caso hemos aplicado primero el operador de indexacin a la lista y luego
hemos accedido al campo dni. El contenido de alumnos i es una Persona, as que podemos
aadir dni para acceder a su campo dni.

389
Disea un programa que pida por teclado los datos de varias personas y los aada
a una lista inicialmente vaca. Cada vez que se lean los datos de una persona el programa
preguntar si se desea continuar introduciendo nuevas personas. Cuando el usuario responda
que no, el programa se detendr.

390
Modifica el programa del ejercicio anterior para que, a continuacin, muestre el
nombre de la persona de ms edad. Si dos o ms personas tienen la mayor edad, el programa
mostrar el nombre de todas ellas.

Dotemos a los objetos de la clase Persona de cierta inteligencia: hagamos que sepan
devolvernos las iniciales de su nombre. Definiremos un mtodo iniciales que devuelva una cadena:
1
2
3
4
5
6
7
8
9

10
11
12

class Persona
def __init__ self nombre dni
self nombre
nombre
self dni
dni
self edad
edad

edad

def iniciales self


cadena
for carcter in self nombre
if carcter
and carcter
cadena
cadena
carcter
return cadena

Ahora nos detendremos a explicar paso a paso cmo hemos definido el nuevo mtodo, pero antes,
veamos si funciona:
Perfecto! Ya te habamos dicho que todos los mtodos tienen un primer parmetro llamado self,
e iniciales no es una excepcin. Cuando efectuamos una llamada a un mtodo siempre lo haremos
sobre una variable del tipo Persona y, en ese caso, self se interpreta como dicha variable.
Cuando hemos ejecutado juan iniciales , el parmetro self se ha interpretado como juan, as
que el acceso a self nombre es, en ese caso, un acceso a juan nombre, es decir, un acceso al
atributo nombre de uno mismo.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

391
Disea un mtodo que permita determinar si una persona es menor de edad devolviendo cierto, si la edad es menor que 18, o falso, en caso contrario.

392
Disea un mtodo nombre_de_pila que devuelva el nombre de pila de una Persona.
Supondremos que el nombre de pila es la primera palabra del atributo nombre (es decir, que no
hay nombres compuestos).
Qu pasa si mostramos con print una variable de tipo Persona?

Mal. No sale lo que esperamos. Definamos un nuevo mtodo que permitir imprimir objetos de
la clase Persona:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18

class Persona
def __init__ self nombre dni
self nombre
nombre
self dni
dni
self edad
edad

edad

def iniciales self


cadena
for carcter in self nombre
if carcter
and carcter
cadena
cadena
carcter
return cadena
def __str__ self
cadena
cadena
cadena
cadena
cadena
return cadena

format self nombre


format self dni
format self edad

Mmmm. Un mtodo llamado __str__. Qu nombre tan extrao! Bueno, funciona ahora?

Ahora s! Ciertos mtodos tienen nombres especiales, como __init__ y __str__. Python espera
que un mtodo con un nombre especial haga algo concreto. Por ejemplo, un mtodo llamado
__init__ debe construir un objeto de la clase Persona y un mtodo llamado __str__ debe devolver
una cadena con lo que queremos que se muestre por pantalla (el str del nombre del mtodo es
una abreviatura de string, es decir, cadena en ingls). En nuestro caso, la cadena que hemos
formado contiene todos los datos de una Persona. Lo realmente curioso acerca de los mtodos
especiales es que no tienes por qu llamarlos directamente: Python los llama automticamente
en ciertos casos. Por ejemplo, cuando haces print de un objeto de la clase Persona, Python le
pregunta al objeto si tiene definido el mtodo __str__ y, si es as, muestra el resultado de
ejecutar dicho mtodo sobre el objeto. Como el resultado de ejecutar __str__ es una cadena,
Python muestra por pantalla esa cadena.

393
Modifica el programa del ejercicio anterior enriqueciendo el tipo de datos Persona
para mujer y
para varn).
con un nuevo campo: el sexo, que codificaremos con una letra (
Aade a tu programa un mtodo __str__ que tambin imprima en pantalla cul es el sexo de la
persona.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7.2.1.

Referencias y objetos

Hemos de tratar ahora un problema que ya nos es conocido. Fjate bien:

Los cambios a copia afectan a juan! Estamos ante el mismo problema que apareci al trabajar
con listas: la asignacin de un objeto a otro solo copia la referencia, y no el contenido.

No solo la asignacin se ve afectada por este hecho: tambin el paso de parmetros se


efecta transmitiendo a la funcin una referencia al objeto, as que los cambios realizados a un
objeto dentro de una funcin son visibles fuera, en el objeto pasado como argumento.
Al trabajar con listas pudimos solucionar el problema obteniendo una copia de la lista a
asignar con el operador de corte o la concatenacin. Pero el operador de corte no tiene significado
alguno para nuestros objetos. Cmo solucionar el problema? Lo normal es que definamos un
mtodo capaz de generar una copia de nuestro objeto y lo usemos cuando sea menester:
1
2
3
4
5
6
7

class Persona

def copia self


nuevo
Persona self nombre
return nuevo

self dni

self edad

Observa que hemos creado y devuelto una nueva Persona cuyos atributos tienen los mismos
valores que tiene self, es decir, la Persona sobre la que invocamos el mtodo.
Repitamos la prueba anterior:

Ahora s! Cmo ha quedado la memoria en este caso? Observa detenidamente la siguiente


figura:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

La verdad es que juan y copia ahora apuntan a objetos de la clase Persona diferentes, pero
no completamente independientes: siguen compartiendo la memoria de las cadenas! Por qu?
Recuerda que la asignacin de una cadena a otra se traduce en la copia de la referencia, no
juan nombre2 el valor de copia nombre es
del contenido, y cuando se ejecuta copia nombre
una referencia a la memoria apuntada por juan nombre.
Como las cadenas son inmutables en Python, no hay problema alguno en que juan y copia
compartan la memoria de sus campos nombre y dni. Aun as, si quisiramos que ambos tuvieran
su propia zona de memoria para estos datos, deberamos modificar el mtodo de copia de la
clase Persona:
1
2
3

class Persona

def copia self


nuevo
Persona self nombre
return nuevo

5
6
7

self dni

self edad

Tras ejecutar las sentencias del ejemplo con el nuevo mtodo copia tenemos:

La gestin de la memoria es un asunto delicado y la mayor parte de los errores graves de


programacin estn causados por un inapropiado manejo de la memoria. Python simplifica mucho
dicha gestin, pero un programador competente debe saber qu ocurre exactamente en memoria
cada vez que se maneja una cadena, lista u objeto.
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

394

Qu mostrar por pantalla la ejecucin del siguiente programa?

class Persona

def nada_til persona1 persona2


persona1 edad
1
persona3
persona2
persona4
persona2 copia
persona3 edad
1
persona4 edad
2
return persona4
juan
Persona
pedro
Persona
otro
nada_til juan
print juan
print pedro
print otro

pedro

19

18

2 En realidad, esta sentencia de asignacin aparece en el programa expresada como self nombre
mtodo __init__ que se ejecuta al construir copia.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

nombre en el

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Haz un diagrama que muestre el estado de la memoria en los siguientes instantes:


a) justo antes de ejecutar la lnea 14,

b) justo antes de ejecutar la lnea 10 en la invocacin de nada_til desde la lnea 14,


c) al finalizar la ejecucin del programa.

7.2.2.

Un ejemplo: gestin de calificaciones de estudiantes

Desarrollemos un ejemplo completo. Vamos a disear un programa que gestiona la lista de


estudiantes de una asignatura y sus calificaciones. De cada estudiante guardaremos su nombre,
su grupo de teora (que ser la letra A, B o C), la nota obtenida en el examen y si ha entregado
o no las prcticas. Tener aprobada la asignatura implica haber entregado las prcticas y haber
obtenido en el examen una nota igual o superior a 5.
Deseamos hacer un programa que permita aadir estudiantes a la lista, mostrar la calificacin
de cada uno de ellos y efectuar algunas estadsticas sobre las notas, como obtener la nota media
o el porcentaje de estudiantes que ha entregado las prcticas.
Definamos primero el tipo de datos Estudiante. Cada estudiante tiene cuatro campos (nombre,
grupo, nota y prctica):
1
2
3
4
5
6

class Estudiante
def __init__ self nombre grupo
self nombre
nombre
self grupo
grupo
self nota
nota
self prctica
prctica

nota

prctica

Los campos nombre y grupo sern cadenas, el campo nota ser un flotante con el valor numrico
de la evaluacin del examen y el valor del campo prctica ser True si la entreg y False en
caso contrario.
Sera interesante definir una funcin que leyera por teclado los datos de un estudiante y
nos devolviera un nuevo objeto Estudiante con sus campos cumplimentados.
1
2
3
4
5
6
7

def lee_estudiante
nombre
input
grupo
input
nota
float input
entregada
input
prctica
entregada
return Estudiante nombre

grupo

nota

prctica

Ojo! lee_estudiante no es un mtodo, sino una funcin, y como tal se define fuera de la clase
Estudiante. La funcin lee de teclado el valor de cada campo y construye un nuevo Estudiante,
que es el valor que devuelve. Podemos pedir al usuario de nuestro programa que introduzca los
datos de un estudiante as:
1

nuevo_estudiante

lee_estudiante

El contenido de nuevo_estudiante es un objeto de la clase Estudiante.


Diseemos ahora una funcin que, dada una lista de estudiantes (posiblemente vaca), pida
los datos de un estudiante y aada el nuevo estudiante a la lista:
1
2

def lee_y_aade_estudiante lista


estudiante
lee_estudiante

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3
4
5
6
7
8
9

10
11
12

lista append estudiante

Definamos ahora el mtodo __str__ para poder imprimir en pantalla un estudiante:

class Estudiante

def __str__ self


cadena
cadena
cadena
cadena
cadena
if self prctica
cadena
cadena
else
cadena
cadena
return cadena

format self nombre


format self grupo
format self nota

395
Disea un procedimiento que, dada una lista de estudiantes, muestre por pantalla
los datos de todos ellos.

396
Disea un procedimiento que, dada una lista de estudiantes y un grupo (la letra A,
B o C), muestre por pantalla un listado completo de dicho grupo.

Ahora nos gustara conocer la calificacin de un estudiante: Matrcula de Honor, Notable,


Aprobado o Suspenso. No existe un campo calificacin en los objetos de la clase Estudiante, as
que deberemos implementar un mtodo que efecte los clculos pertinentes a partir del valor de
prctica y del valor de nota:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17

class Estudiante

def calificacin self


if not self prctica
return
else
if self nota
5
return
elif self nota
7
return
elif self nota
8.5
return
elif self nota
10
return
else
return

Probemos si funciona:

397
Define un mtodo est_aprobado que devuelva True si el alumno ha aprobado la
asignatura y False en caso contrario.

Podemos escribir ahora una funcin que muestre el nombre y la calificacin de todos los
estudiantes:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3

def acta lista


for estudiante in lista
print estudiante nombre

estudiante calificacin

Si queremos obtener algunas estadsticas, como la nota media o el porcentaje de estudiantes


que ha entregado las prcticas, definiremos y usaremos nuevas funciones:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21

def nota_media lista


suma
0
cantidad
0
for estudiante in lista
if estudiante prctica
suma
estudiante nota
cantidad
1
if cantidad
0
return suma
cantidad
else
return 0.0

def porcentaje_de_prcticas_entregadas lista


if len lista
0
cantidad
0
for estudiante in lista
if estudiante prctica
cantidad
1
return cantidad
len lista
100
else
return 0.0

398
Disea una funcin que devuelva el porcentaje de aprobados sobre el total de estudiantes (y no sobre el total de estudiantes que han entregado la prctica).

399
Disea una funcin que reciba una lista de estudiantes y el cdigo de un grupo (la
letra A, B o C) y devuelva la nota media en dicho grupo.

Y esta otra funcin, por ejemplo, devuelve una lista con los estudiantes que obtuvieron la
nota ms alta:
1
2
3
4
5
6
7
8
9

10
11

def mejores_estudiantes lista


nota_ms_alta
0
mejores
for estudiante in lista
if estudiante prctica
if estudiante nota
nota_ms_alta
mejores
estudiante
nota_ms_alta
estudiante nota
elif estudiante nota
nota_ms_alta
mejores append estudiante
return mejores

Fjate en que mejores_estudiantes devuelve una lista cuyos componentes son objetos de la clase
Estudiante. Si deseas listar por pantalla los nombres de los mejores estudiantes, puedes hacer
lo siguiente:
1
2
3

los_mejores
mejores_estudiantes lista
for estudiante in los_mejores
print estudiante nombre

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

o, directamente:
1
2

for estudiante in mejores_estudiantes lista


print estudiante nombre

400
Deseamos realizar un programa que nos ayude a gestionar nuestra coleccin de fi. Cada fichero
contiene una cancin y deseamos almacenar en nuestra base de
cheros
datos la siguiente informacin de cada cancin:
ttulo,

intrprete,

duracin en segundos,
estilo musical.

Empieza definiendo la clase MP3 y su mtodo __init__. Cuando lo tengas, define dos nuevos
mtodos:
resumen: devuelve una cadena con solo el ttulo y el intrprete (en una sola lnea).
__str__: devuelve una cadena con todos los datos del fichero
ocupe una lnea.

de modo que cada campo

A continuacin, disea cuantos mtodos y funciones consideres pertinentes para implementar las
siguientes acciones:
a) aadir una nueva cancin a la base de datos (que ser una lista de objetos de la clase MP3),

b) listar todas las canciones de un intrprete determinado (en formato resumido),


c) listar todas las canciones de un estilo determinado (en formato resumido),

d) listar todas las canciones de la base de datos (en formato completo),

e) eliminar una cancin de la base de datos dado el ttulo y el intrprete.

(Nota: Si quieres que el programa sea realmente til, sera interesante que pudieras salvar la
lista de canciones a disco duro; de lo contrario perders todos los datos cada vez que salgas
del programa. En el prximo captulo aprenderemos a guardar datos en disco y a recuperarlos,
as que este programa solo te resultar realmente til cuando hayas estudiado ese captulo. De
momento, si quieres usarlo ya, puedes utilizar el mdulo pickle que describimos sucintamente
en el captulo anterior).

7.3.

Algunas clases de uso comn

Muchas aplicaciones utilizan ciertos tipos de datos estructurados. Un principio de diseo es


la reutilizacin de cdigo, es decir, no reescribir lo que ya hemos implementado cada vez que
necesitemos usarlo. Nos vendr bien disponer de mdulos en los que hayamos implementado
estas clases de datos. De ese modo, cada aplicacin que necesite utilizar el tipo de datos en
cuestin, solo tendr que importar la clase correspondiente del mdulo.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7.3.1.

La clase fecha

Python no dispone de un tipo de datos fecha, y la verdad es que nos vendra bien en numerosas
aplicaciones. Vamos a disear una clase Fecha y la implementaremos en un mdulo fecha (es
).
decir, en un fichero
Una fecha tiene tres valores: da, mes y ao. Codificaremos cada uno de ellos con un nmero
entero.
1
2
3
4
5

class Fecha
def __init__ self da
self da
da
self mes
mes
self ao
ao

mes

ao

Mmmm. Seguro que nos viene bien un mtodo que muestre por pantalla una fecha.
1
2
3
4
5

class Fecha

def __str__ self


return

format self da

self mes

self ao

401
Define un mtodo llamado formato_largo que devuelva la fecha en un formato ms
.
verboso. Por ejemplo, el 15/4/2002 aparecer como

Definamos ahora un mtodo que indica si un ao es bisiesto o no. Recuerda que un ao es


bisiesto si es divisible por 4, excepto si es divisible por 100 pero no por 400:
1
2
3
4
5

class Fecha

def en_ao_bisiesto self


return self ao
4

0 and

self ao

100

0 or self ao

400

402
Disea un mtodo vlida que devuelva cierto si la fecha es vlida y falso en caso
contrario. Para ello, debes comprobar que el mes est comprendido entre 1 y 12 y que el da
est comprendido entre 1 y el nmero de das que corresponde al mes. Por ejemplo, la fecha
31/4/2000 no es vlida, ya que abril tiene 30 das.
Ten especial cuidado con el mes de febrero: tiene 28 o 29 das segn el ao! Usa, si te
conviene, el mtodo definido en el ejercicio anterior haciendo self en_ao_bisiesto .
1
2
3
4
5
6
7
8
9

10
11
12

Diseemos ahora una funcin (no un mtodo) que lee una fecha por teclado y nos la devuelve:

class Fecha

def lee_fecha
da
0
while da
1 or da
31
da
int input
mes
0
while mes
1 or mes
12
mes
int input
ao
int input
return Fecha da mes ao

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

403
Modifica la funcin lee_fecha para que solo acepte fechas vlidas, es decir, fechas
cuyo da sea vlido para el mes ledo. Puedes utilizar el mtodo vlida desarrollado en el
ejercicio anterior.

Nos gustara comparar dos fechas para saber si una es menor que otra. Podemos disear una
funcin o un mtodo. Implementemos ambas y as remarcaremos las diferencias entre funcin y
mtodo. Empecemos por la funcin:
1
2
3
4
5
6
7
8
9

10

def fecha_es_menor fecha1 fecha2


if fecha1 ao
fecha2 ao
return True
elif fecha1 ao
fecha2 ao
return False
if fecha1 mes
fecha2 mes
return True
elif fecha1 mes
fecha2 mes
return False
return fecha1 da
fecha2 da

Si en un programa deseamos comparar dos fechas, f1 y f2, lo haremos as:


1
2
3

if fecha_es_menor f1

f2

Vamos ahora a por el mtodo:


1
2
3
4
5
6
7
8
9

10
11
12
13

class Fecha

def es_menor_que self la_otra_fecha


if self ao
la_otra_fecha ao
return True
elif self ao
la_otra_fecha ao
return False
if self mes
la_otra_fecha mes
return True
elif self mes
la_otra_fecha mes
return False
return self da
la_otra_fecha da

Observa que tambin tiene dos parmetros, pero el primero es self, es decir, uno mismo, y el
otro es la segunda fecha, la otra. Cmo se usa el mtodo? As:
1
2
3

if f1 es_menor_que f2

A gusto del consumidor.

404
contrario.

Disea un mtodo que devuelva cierto si dos fechas son iguales y falso en caso

405
Disea un mtodo aade_un_da que aade un da a una fecha dada. La fecha
7/6/2001, por ejemplo, pasar a ser 8/6/2002 tras invocar al mtodo aade_un_da sobre ella.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Cuntos das han pasado. . . dnde?

Trabajar con fechas tiene sus complicaciones. Una funcin que calcule el nmero de das transcurridos
entre dos fechas cualesquiera no es trivial. Por ejemplo, la pregunta no se puede responder si no te
dan otro dato: el pas! Sorprendido? No te vendr mal conocer algunos hechos sobre el calendario.
Para empezar, no existe el ao cero, pues el cero se descubri en Occidente bastante ms tarde
(en el siglo IX fue introducido por los rabes, que lo haban tomado previamente del sistema indio). El
ao anterior al 1 d. de C. (despus de Cristo) es el 1 a. de C. (antes de Cristo). En consecuencia, el
da siguiente al 31 de diciembre de 1 a. de C. es el 1 de enero de 1 d. de C.. (Esa es la razn de que
el siglo XXI empezara el 1 de enero de 2001, y no de 2000, como errneamente crey mucha gente).
Julio Csar, en el ao 46 a. C. difundi el llamado calendario juliano. Hizo que los aos empezaran
en 1 de januarius (el actual enero) y que los aos tuvieran 365 das, con un ao bisiesto cada 4 aos,
pues se estimaba que el ao tena 365,25 das. El da adicional se introduca tras el 23 de febrero,
que entonces era el sexto da de marzo, con lo que apareca un da "bis-sexto" (o sea, un segundo da
sexto) y de ah viene el nombre bisiesto de nuestros aos de 366 das. Como la reforma se produjo en
un instante en el que ya se haba acumulado un gran error, Julio Csar decidi suprimir 80 das de
golpe.
Pero la aproximacin que del nmero de das de un ao hace el calendario juliano no es exacta (un
ao dura en realidad 365,242198 das, 11 minutos menos de lo estimado) y comete un error de 7,5 das
cada 1000 aos. En 1582 el papa Gregorio XIII promovi la denominada reforma gregoriana con objeto
de corregir este clculo inexacto. Este papa suprimi los bisiestos seculares (los que corresponden a
aos divisibles por 100), excepto los que caen en aos mltiplos de 400, que siguieron siendo bisiestos.
Para cancelar el error acumulado por el calendario juliano, Gregorio XIII suprimi 10 das de 1582:
el da siguiente al 4 de octubre de 1582 fue el 15 de octubre de 1582. Como la reforma fue propuesta
por un papa catlico, tard en imponerse en pases protestantes u ortodoxos. Inglaterra, por ejemplo,
tard 170 aos en adoptar el calendario gregoriano. En 1752 ya se haba producido un nuevo da
de desfase entre el cmputo juliano y el gregoriano, as que se suprimieron 11 das del calendario:
al 2 de septiembre de 1752 sigui en Inglaterra el 14 de septiembre del mismo ao. Por otra parte,
Rusia no adopt el nuevo calendario hasta 1918!, as que la revolucin de su octubre de 1917 tuvo
lugar en nuestro noviembre de 1917. Y no fue Rusia el ltimo pas occidental en adoptar el calendario
gregoriano: Rumana an tard un ao ms.
Por cierto, el calendario gregoriano no es perfecto: cada 3000 aos (aproximadamente) se desfasa
en 1 da. Menos mal que no nos tocar vivir la prxima reforma!

Atencin al ltimo da de cada mes, pues su siguiente da es el primero del mes siguiente.
Similar atencin requiere el ltimo da del ao. Debes tener en cuenta que el da que sigue al
28 de febrero es el 29 del mismo mes o el 1 de marzo dependiendo de si el ao es bisiesto o no.

406
Disea un mtodo que calcule el nmero de das transcurridos entre la fecha sobre
la que se invoca el mtodo y otra que se proporciona como parmetro. He aqu un ejemplo de
uso:

(No tengas en cuenta el salto de fechas producido como consecuencia de la reforma gregoriana
del calendario. Si no sabes de qu estamos hablando, consulta el cuadro Cuntos das han
pasado. . . dnde?).

407
Modifica el mtodo anterior para que s tenga en cuenta los 10 das perdidos en la
reforma gregoriana. . . en Espaa.

408
Disea un mtodo que devuelva el da de la semana (la cadena
,o
,
etc.) en que cae una fecha cualquiera. (Si sabes en que da cay una fecha determinada, el nmero
de das transcurridos entre esa y la nueva fecha mdulo 7 te permite conocer el da de la semana).

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7.3.2.

Colas y pilas

En numerosas aplicaciones hemos de gestionar colas. Por ejemplo, en un programa de ayuda a


la gestin de una consulta mdica necesitamos manejar una cola de pacientes; o en la gestin
de una lista de espera (una cola) de pasajeros en los vuelos con overbooking. Sera deseable
disponer de un tipo de datos Cola que podamos utilizar en cualquier aplicacin en la que haga
falta. La cola podra comportarse como se muestra en este ejemplo (que, por simplificar, trabaja
con nmeros enteros):

Fjate:

La cola se construye sin ningn argumento (cola


vaca.

Cola

): inicialmente la cola est

El mtodo aade permite aadir elementos al final de la cola.

La funcin print muestra todos los elementos de la cola, empezando por el que entr en
ella en primer lugar. Si la cola est vaca, no muestra nada.

El mtodo primero nos dice quin ocupa la primera posicin de la cola. Si la cola est
vaca, devuelve None.
El mtodo sacaPrimero elimina al primer elemento de la cola. Si la cola est vaca, no
hace nada.
El mtodo tamao nos dice cuntos elementos hay en la cola.

El mtodo esVaca nos dice si la cola est vaca o no, devolviendo cierto o falso.

Nuestro primer problema es decidir cmo guardamos la informacin propia de una cola y la
respuesta es muy fcil: con una lista.
1
2
3

class Cola
def __init__ self
self cola

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Hemos guardado la lista en el atributo cola y la hemos inicializado con la lista vaca. El
constructor __init__ no necesita parmetro alguno (salvo, self, naturalmente), pues una cola
nueva siempre empieza estando vaca.
El mtodo aade es sencillo de implementar: se limita a aadir a la lista un nuevo elemento
por el final.
1
2
3
4
5

class Cola

def aade self elemento


self cola append elemento

El mtodo primero nos dice quin ocupa la primera posicin de la cola, es decir, quin ocupa
self cola 0 :
1
2
3
4
5
6
7
8

1
2
3
4
5
6

class Cola

def primero self


if len self cola
0
return None
else
return self cola 0

Y el mtodo sacaPrimero sencillamente borra el primer elemento de la lista:

class Cola

def sacaPrimero self


if len self cola
0
del self cola 0

El resto de mtodos no plantea dificultad alguna, as que los mostramos todos sin ms dilacin:
1
2
3
4
5
6
7
8
9

10
11
12
13
14

class Cola

def __str__ self


cadena
for elemento in self cola
cadena
cadena
str elemento
return cadena
def tamao self
return len self cola
def esVaca self
return len self cola

409
Disea un mtodo copia que devuelva una nueva Cola cuyo contenido es el mismo
de la Cola sobre la que se invoca el mtodo. Ojo con la memoria cuando saques una copia de
self cola!
410
Disea un programa que gestiona una lista de espera de pacientes usando la clase
Cola definida en este apartado. Cada paciente tiene un nombre y un nmero de la seguridad

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

social. El programa presentar un men con las siguientes opciones: 1) aadir un paciente a la
lista de espera; 2) atender al primer paciente de la lista; y 3) finalizar la ejecucin del programa.
Al seleccionar un paciente se solicitarn los datos del paciente y se aadir este a la lista de
espera (que es una cola). Al seleccionar la segunda opcin, aparecer en pantalla el nombre del
paciente y se eliminar a este de la cola. La lista de espera respetar estrictamente el orden de
llegada de los pacientes.

411
Modifica el programa anterior para que gestione dos colas: una para atencin mdica
normal y otra para urgencias. Al aadir un paciente se preguntar si se trata de una urgencia
o no. En el primer caso, se aadir a una lista de espera de urgencias y en el segundo, a una
lista de espera normal. Cada vez que se seleccione la segunda opcin del men aparecer el
nombre de un paciente en pantalla, pero tendrn preferencia aquellos que estn en la lista de
espera de urgencias. Ningn paciente de la cola normal ser atendido mientras haya uno solo
en la cola de urgencias. Dentro de cada cola se respetar estrictamente el orden de llegada.

412
Implementa ahora el tipo Pila. Una pila es una lista de elementos en la que el primero
que entra es el ltimo en salir. Debes montar los siguientes mtodos (adems del constructor):
apila: introduce un nuevo elemento en la pila,

desapila: extrae el ltimo elemento introducido en la pila,

cima: devuelve el ltimo elemento introducido en la pila (pero sin modificar la pila),
tamao: dice cuntos elementos hay apilados,

es_vaca: devuelve cierto si la pila est vaca y falso en caso contrario.

7.3.3.

Colas de prioridad

Las colas de prioridad son unas colas un tanto especiales: sus elementos se insertan en cualquier
orden, pero el elemento que sale en primer lugar siempre es el que presenta mayor prioridad.
Tenemos varias alternativas para implementar una cola de prioridad3 :

a) representarla internamente mediante una lista que en todo momento est ordenada de mayor
a menor prioridad,

b) representarla internamente mediante una lista desordenada, buscando el elemento de mayor


prioridad cada vez que se precise.
Desarrollaremos el segundo caso, pero te proponemos como ejercicio que desarrolles t mismo
el primero.
Las operaciones que podremos realizar con una cola de prioridad son:
Construirla (__init__): crea una cola de prioridad vaca.

Insertar un elemento (inserta): aade un elemento a la cola.

Consultar el primer elemento (primero): devuelve el elemento de mayor prioridad, pero no


lo elimina de la cola.
Extraer (extrae): devuelve el elemento de mayor prioridad y lo elimina de la cola.
Consultar su tamao (tamao): devuelve el nmero de elementos encolados.

Consultar si est vaca (es_vaca): devuelve cierto si la cola est vaca y falso en caso
contrario.

3 Con

lo que sabemos hacer de momento, solo tenemos esas dos posibilidades. Ambas son muy ineficientes, pero an
es pronto para que sepas por qu. Las colas de prioridad pueden implementarse con montculos (heaps, en ingls) u
otras estructuras de datos avanzadas.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Implementemos:
1
2
3
4
5

class ColaPrioridad
def __init__ self
self cola

def inserta self valor


self cola append valor

6
7

def primero self valor


if len self cola
0
return None
mximo
self cola 0
for elemento in self cola
if elemento
mximo
mximo
elemento
return mximo

8
9

10
11
12
13
14
15
16

def extrae self valor


if len self cola
0
return None
ndice
0
for i in range len self cola
if self cola i
self cola ndice
ndice
i
aux
self cola ndice
del self cola ndice
return aux

17
18
19
20
21
22
23
24
25
26
27

def tamao self


return len self cola

28
29
30

def es_vaca self


return len self cola

31
32

413

Implementa una cola de prioridad utilizando internamente una lista siempre ordenada.

414
Vamos a mejorar el programa de gestin de colas de pacientes desarrollado en el
apartado anterior. Ahora vamos a clasificar los pacientes segn la gravedad de su dolencia en
20 niveles de prioridad distintos. El nivel 20 es el ms prioritario, el que requiere la ms urgente
atencin, y el 1 es el menos prioritario.
Podramos gestionar 20 colas distintas, una para cada prioridad, pero resulta ms elegante
gestionar una nica cola de prioridad. Para ello, en lugar de encolar nicamente el nombre de
un paciente, puedes encolar una lista con dos o ms datos (como mnimo debers almacenar la
prioridad y el nombre del paciente).

7.3.4.

Conjuntos

Es probable que en nuestras aplicaciones necesitemos utilizar conjuntos, es decir, colecciones


de datos en las que cada elemento de un universo est o no est presente. Una lista no es un
conjunto porque es posible que un elemento aparezca repetidas veces. Podemos simular el tipo
de datos conjunto con una simple lista, pero teniendo siempre la precaucin de no insertar un
elemento si ya est presente. Para no complicar nuestros programas con constantes consultas
a listas para determinar si los elementos a insertar estn o no ya presentes, es mejor definir
un nuevo tipo de datos que, internamente, realice las comprobaciones pertinentes: una clase
Conjunto. Es ms, podemos enriquecer el nuevo tipo de datos con operaciones de conjuntos
tiles: la interseccin, la unin, la diferencia, etc.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

En primer lugar nos hemos de plantear qu atributos tendr un Conjunto. Bastar con una
lista que contenga los elementos presentes en el conjunto. Inicialmente, la lista estar vaca:
1
2
3

class Conjunto
def __init__ self
self elementos

Necesitamos definir ahora un mtodo para la insercin de elementos. El mtodo inserta


recibir dos argumentos: self (como siempre) y el elemento que deseamos insertar. Antes de
aadir el elemento a la lista, nos preguntaremos si ya est presente, porque solo deberemos
hacer algo en caso contrario:
1
2
3
4
5
6

class Conjunto

def inserta self elemento


if not elemento in self elementos
self elementos append elemento

415
Enriquece la clase Conjunto con un mtodo elimina que borre del conjunto un elemento dado. (Solo habr que borrar el elemento de la lista si est presente, claro est).

Definamos ahora un mtodo para imprimir un conjunto por pantalla. Estara bien que los
conjuntos aparecieran por pantalla con el aspecto tradicional: con sus elementos separados
por comas y encerrados en un par de llaves.
1
2
3
4
5
6
7
8
9

10

class Conjunto

def __str__ self


cadena
if len self elementos
0
for elemento in self elementos
1
cadena
cadena
str elemento
cadena
cadena
str self elementos
return cadena

He aqu un ejemplo de uso de Conjunto:

Otro mtodo til nos permite preguntar a un conjunto por su talla, es decir, el nmero de
elementos que lo forman:
1
2
3
4
5

class Conjunto

def talla self


return len self elementos

Nos vendr bien disponer de un mtodo que permita consultar si un elemento pertenece o
no a un conjunto:
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3

class Conjunto

def pertenece self elemento


return elemento in self elementos

4
5

416
Disea un mtodo es_vaco que devuelva cierto si el conjunto est vaco y falso en
caso contrario.

Vamos a por las operaciones entre conjuntos. Definamos la unin de conjuntos con un mtodo
que devuelva el conjunto resultante de unir al conjunto self otro conjunto:
1
2
3

class Conjunto

def unin self otro


C
Conjunto
C elementos
self elementos
for elemento in otro elementos
C inserta elemento
return C

4
5
6
7
8
9

Observa cmo se usa unin:

417
Disea un mtodo interseccin que devuelva un conjunto con la interseccin de dos
conjuntos (uno de ellos ser aquel sobre el que se invoca el mtodo y otro se pasar como
parmetro).

418
Disea un mtodo diferencia que devuelva un conjunto con la diferencia entre dos
conjuntos, es decir, con aquellos elementos que estn en el primero, pero no en el segundo.

Finalmente, he aqu un mtodo que consulta si otro conjunto dado est incluido en el conjunto
(self ):
1
2
3

class Conjunto

4
5
6
7
8

7.4.

def incluye self otro


for elemento in otro elementos
if not elemento in self elementos
return False
return True

Un ejemplo completo: gestin de un videoclub

En este apartado vamos a desarrollar un ejemplo completo y til usando clases: un programa
para gestionar un videoclub. Empezaremos creando la aplicacin de gestin para un videoclub
bsico, muy simplificado, e iremos complicndola poco a poco.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

Ms mtodos especiales

Hemos visto que las clases admiten dos mtodos especiales: __init__ y __str__. No son los nicos
mtodos especiales. Podemos hacer que las clases se comporten de modo similar a los tipos de datos
nativos de Python definiendo muchos otros mtodos especiales. He aqu unos pocos:
__len__ self : Permite aplicar la funcin predefinida len sobre objetos de la clase. Debe
devolver la longitud o talla del objeto. En el caso de colas y conjuntos, por ejemplo,
correspondera al nmero de elementos. Si A es un Conjunto, podramos usar len A si antes
hubisemos definido el mtodo __len__.

__add__ self otro : Permite aplicar el operador de suma (+) a objetos de la clase sobre
la que se ha definido. Si, por ejemplo, A y B son conjuntos, la expresin C
A
B permite
asignar al nuevo conjunto C la unin de ambos.
__mul__ self otro : Permite aplicar el operador de multiplicacin (*) a objetos de la clase
sobre la que se ha definido.

__cmp__ self otro : Permite aplicar los operadores de comparacin ( , , , , , ) a


objetos de una clase. Debe devolver -1 si self es menor que otro, 0 si son iguales y 1 si self
es mayor que otro.
Podemos, por ejemplo, definir __cmp__ en Persona para que devuelva -1 cuando la edad
self edad es menor que otro edad, 0 si son iguales y 1 si self edad es mayor que otro edad.
Si juan y pedro son personas, podremos compararlas con expresiones como juan
pedro o
juan
pedro.

Consulta la documentacin de Python si quieres conocer todos los mtodos especiales que puedes definir en tus clases. Tus programas pueden ganar mucho en elegancia si defines los mtodos apropiados
para cada clase.

7.4.1.

Videoclub bsico

El videoclub tiene un listado de socios. Cada socio tiene una serie de datos:
dni,

nombre,

telfono,

domicilio.

Por otra parte, disponemos de una serie de pelculas. De cada pelcula nos interesa:
ttulo,

gnero (accin, comedia, musical, etc.).

Supondremos que en nuestro videoclub bsico solo hay un ejemplar de cada pelcula.
Empecemos definiendo los tipos bsicos con sus mtodos especiales: el constructor __init__
y el conversor a cadena __str__:
1
2
3
4
5
6
7
8
9

10
11

class Socio
def __init__ self dni nombre
self dni
dni
self nombre
nombre
self telfono
telfono
self domicilio
domicilio
def __str__ self
return
format self dni

telfono

self nombre

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

domicilio

self telfono

self domicilio

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

12
13
14
15
16
17
18

class Pelcula
def __init__ self ttulo gnero
self ttulo
ttulo
self gnero
gnero
def __str__ self
return

format self ttulo

self gnero

Podemos definir tambin una clase Videoclub que mantenga y gestione las listas de socios
y pelculas:
1
2
3
4

class Videoclub
def __init__ self
self socios
self pelculas

Nuestra aplicacin presentar un men con diferentes opciones. Empecemos por implementar
las ms sencillas: dar de alta/baja a un socio, dar de alta/baja una pelcula. La funcin men
mostrar el men de operaciones y leer la opcin que seleccione el usuario de la aplicacin.
Nuestra primera versin ser esta:
1
2
3
4
5
6
7
8
9

10
11

def men
print
print
print
print
print
print
opcin
int input
while opcin
1 or opcin
opcin
int input
return opcin

En una variable videoclub tendremos una instancia de la clase Videoclub, y es ah donde


almacenaremos la informacin del videoclub. Nuestra primera versin del programa presentar
este aspecto:
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20

videoclub

Videoclub

opcin
men
while opcin

if opcin
1
print
socio
nuevo_socio
if videoclub contiene_socio socio dni
print
else
videoclub alta_socio socio

dni

elif opcin
2
print
dni
input
if videoclub contiene_socio dni
videoclub baja_socio dni
print
dni
else

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

print

elif opcin
3
print
pelcula
nueva_pelcula
if videoclub contiene_pelcula pelcula ttulo
print
else
videoclub alta_pelcula pelcula
elif opcin
4
print
ttulo
input
if videoclub contiene_pelcula ttulo
videoclub baja_pelcula ttulo
else
print

opcin

men

dni

pelcula ttulo

ttulo

Analicmoslo por partes. Empecemos por el fragmento de cdigo que corresponde al alta de
un socio. Lo primero que hacemos es pedir la creacin de un nuevo socio mediante la funcin
nuevo_socio. Esta funcin leer de teclado los datos. Definmosla:
1
2
3
4
5
6

def nuevo_socio
dni
input
nombre
input
telfono
input
domicilio
input
return Socio dni nombre

telfono

domicilio

El socio devuelto por nuevo_socio puede haber sido dado de alta previamente en el videoclub,
con lo que no sera procedente darlo de alta ahora. A continuacin se pregunta al videoclub si
ya tiene algn socio con el DNI del nuevo socio. Si es as, se muestra un aviso por pantalla, y
si no, se da de alta al socio. Observa que se usan dos mtodos del videoclub: contiene_socio,
que recibe un DNI y devuelve cierto o falso, y alta_socio, que recibe un socio y lo aade a su
lista de socios. Su definicin sera:
1
2
3
4
5
6
7
8
9

10
11

class Videoclub

def contiene_socio self dni


for socio in self socios
if socio dni
dni
return True
return False

def alta_socio self socio


self socios append socio

Estudiemos ahora el fragmento de cdigo para dar de baja a un socio. En primer lugar, se
pide su DNI. Si el socio existe (lo que se averigua con el mtodo contiene_socio, definido justo
antes), se le da de baja llamando al mtodo baja_socio, que recibe el DNI. Si ningn socio tiene
el DNI suministrado, se advierte al usuario del programa con un aviso. Hemos de definir, pues,
baja_socio:

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

1
2
3

class Videoclub

def baja_socio self dni


for i in range len self socios
if self socios i dni
dni
del self socios i
break

4
5
6
7
8

419

Define t mismo los procedimientos que dan de alta/baja una pelcula.

De poca utilidad ser el programa si no permite alquilar las pelculas. Cmo haremos para
representar que una pelcula est alquilada a un socio? Tenemos (al menos) dos posibilidades:
aadir un atributo a cada Socio indicando qu pelcula tiene en alquiler (y si no tiene
ninguna, su valor ser None, por ejemplo),
aadir un atributo a cada Pelcula indicando a quin est alquilada (y si no est alquilada,
su valor ser None, por ejemplo).

Parece mejor la segunda opcin: una operacin que realizaremos con frecuencia es preguntar si
una pelcula est alquilada o no; por contra, preguntar si un socio tiene o no pelculas alquiladas
parece una operacin menos frecuente.
As pues, tendremos que modificar la definicin de la clase Pelcula:
1
2
3
4
5
6
7
8
9

10
11
12
13

class Pelcula
def __init__ self ttulo gnero
self ttulo
ttulo
self gnero
gnero
self alquilada
None
def __str__ self
cadena
if self alquilada
None
cadena
cadena
else
cadena
cadena
return cadena

format self ttulo

self gnero

format self alquilada

Observa que el atributo alquilada no se pasa como parmetro a __init__. La razn es muy
simple: cuando construimos una nueva pelcula no est alquilada a nadie, as que el atributo
alquilada siempre empieza valiendo None. Para qu pasar como argumento a __init__ un valor
que no aporta informacin alguna?
Aadamos ahora un mtodo que permita alquilar una pelcula (dado su ttulo) a un socio
(dado su DNI). La llamada a este mtodo se asociar a la opcin 5 del men, y el final de
ejecucin de la aplicacin se asociar ahora a la opcin 6.
1
2
3
4
5
6
7
8
9

videoclub
opcin

Videoclub

men

while opcin

if opcin

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

elif opcin
5
print
ttulo
input
dni
input
hay_pelcula
videoclub contiene_pelcula ttulo
hay_socio
videoclub contiene_socio dni
if hay_pelcula and hay_socio
videoclub alquilar_pelcula ttulo dni
else
if not hay_pelcula
print
ttulo
if not hay_socio
print
dni
opcin
men

Diseemos el mtodo alquilar_pelcula. Supondremos que existe una pelcula cuyo ttulo
corresponde al que nos indican y que existe un socio cuyo DNI es igual al que nos pasan como
argumento, pues ambas comprobaciones se efectan antes de llamar al mtodo.
1
2
3
4
5
6
7
8

class Videoclub

def alquilar_pelcula self ttulo dni


for pelcula in self pelculas
if pelcula ttulo
ttulo and pelcula alquilada
pelcula alquilada
dni
break

None

En principio, ya est. El mtodo alquilar_pelcula recorre la lista de pelculas del videoclub


y solo efecta el alquiler cuando encuentra una con el ttulo que nos dan y esta est disponible.
Pero podemos mejorarlo: el mtodo no nos informa de si finalmente alquil o no la pelcula en
cuestin, lo que hace que no podamos informar al usuario de si la operacin se realiz con xito
o no. Vamos a modificarlo para que devuelva cierto si alquil efectivamente la pelcula, y falso
en caso contrario.
1
2
3
4
5
6
7
8
9

10
11

1
2
3
4
5
6

class Videoclub

def alquilar_pelcula self ttulo dni


for pelcula in self pelculas
if pelcula ttulo
ttulo
if pelcula alquilada
None
pelcula alquilada
dni
return True
else
return False

Ahora podemos modificar las acciones asociadas a la opcin 5:

videoclub

Videoclub

opcin
men
while opcin
if opcin

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

elif opcin
5
ttulo
input
dni
input
hay_pelcula
videoclub contiene_pelcula ttulo
hay_socio
videoclub contiene_socio dni
if hay_pelcula and hay_socio
if videoclub alquilar_pelcula ttulo dni
print
else
print
else
if not hay_pelcula
print
ttulo
if not hay_socio
print
dni
opcin
men

420
Aade una nueva funcionalidad al programa: la devolucin de una pelcula alquilada.
Disea para ello un mtodo devolver_pelcula que, dado el ttulo de la pelcula, devuelve True si
estaba alquilada y False en caso contrario. Adems, si estaba alquilada, el mtodo la marcar
como disponible (pondr a None el valor del campo alquilada).
A continuacin, aade una opcin al men para devolver una pelcula. Las acciones asociadas
son:
pedir el nombre de la pelcula;

si no existe una pelcula con ese ttulo, dar el aviso pertinente y no hacer nada ms;

si existe la pelcula pero no estaba alquilada, avisar al usuario y no hacer nada ms;
y si existe la pelcula y estaba alquilada, marcarla como disponible.

421
Modifica los mtodos que dan de baja a un socio o una pelcula para que no se
permita dar de baja una pelcula alquilada ni a un socio que tiene alguna pelcula en alquiler.
Si no fue posible dar de baja el socio o la pelcula, el mtodo correspondiente devolver
False. Si, por el contrario, se pudo dar de baja a uno u otro, devolver True.
Modifica a continuacin las acciones asociadas a las respectivas opciones del men para que
den los avisos pertinentes en caso de que no sea posible dar de baja a un socio o una pelcula.

Finalmente, vamos a ofrecer la posibilidad de efectuar una consulta interesante a la coleccin


de pelculas del videoclub. Es posible que un cliente nos pida que le recomendemos pelculas
disponibles dado el gnero que a l le gusta. Un mtodo de Videoclub permitir obtener este
tipo de listados.
1
2
3
4
5
6
7

class Videoclub

def listado_por_gnero self gnero


for pelcula in self pelculas
if pelcula gnero
gnero and pelcula alquilada
print ttulo

None

Solo resta aadir una opcin de men que pida el gnero para el que solicitamos el listado
e invoque al mtodo listado_por_gnero.

422
Modifica listado_por_gnero para que muestre todas las pelculas del videoclub, pero
indicando al lado del ttulo si est alquilada o disponible.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7.4.2.

Un videoclub ms realista

El programa que hemos hecho presenta ciertos inconvenientes por su simplicidad: por ejemplo,
asume que solo existe un ejemplar de cada pelcula y, al no llevar registro de las fechas de
alquiler, permite que un socio alquile una pelcula un nmero indeterminado de das. Mejoremos
el programa corrigiendo ambos defectos.
Tratemos en primer lugar la cuestin de la existencia de varios ejemplares por pelcula. Est
claro que la clase Pelcula ha de sufrir algunos cambios. Tenemos (entre otras) dos posibilidades:
a) hacer que cada objeto de la clase Pelcula corresponda a un ejemplar, es decir, permitir que
la lista pelculas contenga ttulos repetidos (una vez por cada ejemplar).

b) enriquecer cada pelcula con un campo ejemplares que indique cuntos ejemplares tenemos.

Mmmm. La segunda posibilidad requiere un estudio ms detallado. Con solo un contador de


ejemplares no es suficiente. Cmo representaremos el hecho de que, por ejemplo, de 5 ejemplares,
3 estn alquilados, cada uno a un socio diferente? Ser preciso enriquecer la informacin propia
de una Pelcula con una lista que contenga un elemento por cada ejemplar alquilado. Cada
elemento de la lista deber contener, como mnimo, algn dato que identifique al socio al que
se alquil la pelcula.
Parece, pues, que la primera posibilidad es ms sencilla de implementar. Desarrollaremos
esa, pero te proponemos como ejercicio que desarrolles t la segunda posibilidad.
En primer lugar, modificaremos el mtodo que da de alta una pelcula para que nos pida el
nmero de ejemplares que aadimos al videoclub.
1
2
3
4
5
6
7

class Videoclub

def alta_pelcula self pelcula ejemplares


for i in range ejemplares
nuevo_ejemplar
Pelcula pelcula ttulo
self pelculas append nuevo_ejemplar

pelcula gnero

Al dar de alta ejemplares de una pelcula ya no ser necesario comprobar si existe ese ttulo
en nuestra coleccin de pelculas:
1
2
3
4
5
6
7
8

elif opcin
3
print
pelcula
nueva_pelcula
ejemplares
int input
videoclub alta_pelcula pelcula

ejemplares

Dar de baja un nmero de ejemplares de un ttulo determinado no es muy difcil, aunque


puede aparecer una pequea complicacin: que no podamos eliminar efectivamente el nmero
de ejemplares solicitado, bien porque no hay tantos en el videoclub, bien porque alguno de
ellos est alquilado. Haremos que el mtodo que da de baja el nmero de ejemplares solicitado
nos devuelva el nmero de ejemplares que realmente pudo dar de baja, de ese modo al menos
avisamos a quien nos llama de lo que realmente hicimos.
1
2
3
4
5

class Videoclub

def baja_pelcula self ttulo


bajas_efectivas
0

ejemplares

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

6
7
8
9

10
11
12
13

i
0
while i
len self pelculas
if self pelculas i ttulo
del pelculas i
bajas_efectivas
1
else
i
1
return bajas_efectivas

ttulo and self pelculas i

alquilada

None

Veamos cmo queda el fragmento de cdigo asociado a la accin de men que da de baja
pelculas:
1
2
3
4
5
6
7
8
9

10
11
12
13

elif opcin
4
print
ttulo
input
ejemplares
int input
bajas
videoclub baja_pelcula ttulo
if bajas
ejemplares
print
else
print

ejemplares
bajas

El mtodo de alquiler de una pelcula a un socio necesita una pequea modificacin: puede
que los primeros ejemplares encontrados de una pelcula estn alquilados, pero no estamos
seguros de si hay alguno libre hasta haber recorrido la coleccin entera de pelculas. El mtodo
puede quedar as:
1
2
3
4
5
6
7
8
9

10

class Videoclub

def alquilar_pelcula self ttulo dni


for pelcula in self pelculas
if pelcula ttulo
ttulo
if pelcula alquilada
None
pelcula alquilada
dni
return True
return False

Observa que solo devolvemos False cuando hemos recorrido la lista entera de pelculas sin
haber podido encontrar una libre.

423
Implementa el nuevo mtodo de devolucin de pelculas. Ten en cuenta que necesitars
dos datos: el ttulo de la pelcula y el DNI del socio.

Ahora podemos modificar el programa para que permita controlar si un socio retiene la pelcula ms das de los permitidos y, si es as, que nos indique los das de retraso. Enriqueceremos
la clase Pelcula con nuevos atributos:
fecha_alquiler: contiene la fecha en que se realiz el alquiler.
das_permitidos: nmero de das de alquiler permitidos.

Parece que ahora hemos de disponer de cierto control sobre las fechas. Afortunadamente ya
hemos construido una clase Fecha en este mismo captulo. Utilicmosla!
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

424
Modifica el constructor de Pelcula para aadir los nuevos atributos. Modifica a
continuacin alta_pelcula para que pida tambin el valor de das_permitidos.

Empezaremos por aadir una variable global, a la que llamaremos hoy, que contendr la
fecha actual4 :
1
2
3
4
5

from fecha import Fecha


Programa principal
hoy
lee_fecha

lee_fecha

Cuando alquilemos una pelcula no solo apuntaremos el socio al que la alquilamos, tambin
recordaremos la fecha del alquiler:
1
2
3

class Videoclub

def alquilar_pelcula self ttulo dni


for pelcula in self pelculas
if pelcula ttulo
ttulo
if pelcula alquilada
None
pelcula alquilada
dni
pelcula fecha_alquiler
hoy
return True
return False

4
5
6
7
8
9

10
11

Otro procedimiento afectado por la introduccin de fechas es el de devolucin de pelculas.


No nos podemos limitar a devolver la pelcula: hemos de comprobar si se incurre en retraso y,
por tanto, se debe pagar una multa.

425
Modifica el mtodo de devolucin de pelculas para que tenga en cuenta la fecha de
alquiler y la fecha de devolucin. El mtodo devolver el nmero de das de retraso. (Supn que
nuestra clase Fecha dispone de un mtodo das_trascurridos que devuelve el nmero de das
transcurridos desde una fecha determinada).
Modifica las acciones asociadas a la opcin de men de devolucin de pelculas para que
tenga en cuenta el valor devuelto por el mtodo devolver_pelcula y muestre por pantalla el
nmero de das de retraso (si es el caso).

426
Modifica el mtodo listado_por_gnero para que un mismo ttulo de una pelcula
si hay al
no aparezca ms que una vez. Al lado del ttulo aparecer la cadena
si todos los ejemplares estn alquilados.
menos un ejemplar disponible y

7.4.3.

Listado completo

Nos ha salido un programa larguito. Vale la pena que mostremos un listado completo.
1
2
3
4
5
6
7

=============================
videoclub
=============================
Programa para la gestin de videoclubs.
=============================

from fecha import Fecha

lee_fecha

4 Lo natural sera que la fecha actual se fijara automticamente a partir del reloj del sistema. Puedes hacerlo usando
el mdulo time. Consulta el manual de la librera.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

Socio

Clase para almacenar los datos relativos a un socio.

class Socio
def __init__ self dni nombre telfono domicilio
self dni
dni
self nombre
nombre
self telfono
telfono
self domicilio
domicilio
def __str__ self
return
format self dni

self nombre

self telfono

Pelcula

Clase para almacenar los datos relativos a un ejemplar de una


pelcula.

class Pelcula
def __init__ self ttulo gnero das_permitidos
self ttulo
ttulo
self gnero
gnero
self alquilada
None
self fecha_alquiler
None
self das_permitidos
das_permitidos
def __str__ self
cadena
if self alquilada
None
cadena
cadena
else
cadena
cadena
return cadena

self domicilio

format self ttulo

self gnero

format self alquilada

Videoclub

Almacena dos listas: una de socios y otra de pelculas. Los


elementos de la primera lista son de la clase Socio, y los de la
segunda, de la clase Pelcula.

class Videoclub
def __init__ self
self socios
self pelculas

def contiene_socio self dni


Devuelve True si existe algn socio con DNI dni y False en caso
contrario.
for socio in self socios
if socio dni
dni
return True
return False
def contiene_pelcula self ttulo
Devuelve True si existe alguna pelcula del ttulo que nos

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

pasan y False en caso contrario.


for pelcula in self pelculas
if pelcula ttulo
ttulo
return True
return False

def alta_socio self socio


Aade un socio a la lista de socios.
Requisito: no debe existir ningn socio con el mismo DNI.
self socios append socio
def baja_socio self dni
Elimina al socio cuyo DNI es igual a dni.
Requisito: debe existir un socio con ese DNI.
for i in range len self socios
if self socios i dni
dni
del self socios i
break

def alta_pelcula self pelcula ejemplares


Da de alta un nmero dado de ejemplares de una pelcula.
for i in range ejemplares
nuevo_ejemplar
Pelcula pelcula ttulo pelcula gnero
pelcula das_permitidos
self pelculas append nuevo_ejemplar

def baja_pelcula self ttulo ejemplares


Da de baja un nmero de ejemplares de la pelcula cuyo ttulo nos
suministran como argumento. Devuelve el nmero de ejemplares que
se dio de baja efectivamente.
bajas_efectivas
0
i
0
while i
len self pelculas and bajas_efectivas
ejemplares
if self pelculas i ttulo
ttulo and self pelculas i alquilada
del self pelculas i
bajas_efectivas
1
else
i
1
return bajas_efectivas

None

def alquilar_pelcula self ttulo dni


Alquila un ejemplar de la pelcula cuyo ttulo nos indican, al socio
con DNI dni. Si no consigue efectuar el alquiler, devuelve False, y True
si lo consigue. La fecha de alquiler se fija automticamente al da
actual.
Requisito: debe existir un socio con el DNI suministrado.
for pelcula in self pelculas
if pelcula ttulo
ttulo and pelcula alquilada
None
pelcula alquilada
dni
pelcula fecha_alquiler
hoy
return True
return False
def devolver_pelcula self ttulo dni
Devuelve un ejemplar de la pelcula cuyo ttulo nos indican que
estaba alquilada al socio con DNI dni. Devuelve el nmero de das
de retraso, o -1 si ningn ejemplar de la pelcula est alquilado
al socio.
Requisito: debe existir un socio con el DNI suministrado.
for pelcula in self pelculas
if pelcula ttulo
ttulo and pelcula alquilada
dni

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

return

pelcula alquilada
None
das_retraso
pelcula fecha_alquiler das_transcurridos hoy
return das_retraso
1

def listado_por_gnero self gnero


Muestra un listado de las pelculas cuyo gnero es el indicado.
Cada ttulo aparece solo una vez. Al lado del ttulo aparece
una indicacin sobre si hay o no hay ejemplares disponibles para
alquiler.
disponibles
alquiladas
for pelcula in self pelculas
if pelcula gnero
gnero
if pelcula alquilada
None and not pelcula ttulo in disponibles
disponibles append pelcula ttulo
if pelcula alquilada
None and not pelcula ttulo in alquiladas
alquiladas append pelcula ttulo
for ttulo in disponibles
print ttulo
for ttulo in alquiladas
if not ttulo in disponibles
print ttulo

.....................................................................
Funciones
.....................................................................

def men
Muestra el men por pantalla y lee una opcin de teclado, que es el
resultado devuelto.
La funcin se asegura de que la opcin leda est entre 0 y 8.
print
print
print
print
print
print
print
print
print
print
opcin
int input
while opcin
0 or opcin
opcin
int input
return opcin

def nuevo_socio
Pide por teclado los datos de un nuevo socio y devuelve un objeto
de la clase Socio.
dni
input
nombre
input
telfono
input
domicilio
input
return Socio dni nombre telfono domicilio
def nueva_pelcula
Pide por teclado los datos de una nueva pelcula y devuelve un
objeto de la clase Pelcula.
ttulo
input

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251

gnero
input
das_permitidos
input
return Pelcula ttulo gnero

das_permitidos

Programa principal

Fijar fecha actual


hoy
lee_fecha
videoclub

Videoclub

opcin
men
while opcin
if opcin
print
hoy

lee_fecha

elif opcin
1
print
socio
nuevo_socio
if videoclub contiene_socio socio dni
print
else
videoclub alta_socio socio

dni

elif opcin
2
print
dni
input
if videoclub contiene_socio dni
videoclub baja_socio dni
print
dni
else
print
elif opcin
3
print
pelcula
nueva_pelcula
ejemplares
int input
videoclub alta_pelcula pelcula

dni

ejemplares

elif opcin
4
print
ttulo
input
ejemplares
int input
bajas
videoclub baja_pelcula ttulo
if bajas
ejemplares
print
else
print

ejemplares
bajas

elif opcin
5
print
ttulo input
dni
input
hay_pelcula
videoclub contiene_pelcula ttulo
hay_socio
videoclub contiene_socio dni
if hay_pelcula and hay_socio
if videoclub alquilar_pelcula ttulo dni

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

252
253
254
255
256
257

else

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286

else

print
print

if not hay_pelcula
print
if not hay_socio
print

dni

ttulo

elif opcin
6
print
ttulo input
dni
input
hay_pelcula
videoclub contiene_pelcula ttulo
hay_socio
videoclub contiene_socio dni
if hay_pelcula and hay_socio
resultado
videoclub devolver_pelcula ttulo dni
if resultado
0
print
elif resultado
0
print
else
print
ttulo
else
if not hay_pelcula
print
ttulo
if not hay_socio
print
dni

resultado

dni

elif opcin
7
print
gnero
input
videoclub listado_por_gnero gnero
opcin

men

El programa de gestin de un videoclub que hemos desarrollado dista de ser perfecto. Muchas de las operaciones que hemos implementado son ineficientes y, adems, mantiene toda
la informacin en memoria RAM, as que pierde toda la informacin al finalizar la ejecucin.
Tendremos que esperar al prximo captulo para abordar el problema del almacenamiento de
informacin de modo que recuerde su estado entre diferentes ejecuciones.
Bases de datos

Muchos programas de gestin manejan grandes volmenes de datos. Es posible disear programas como el del videoclub (con almacenamiento de datos en disco duro, eso s) que gestionen adecuadamente
la informacin, pero, en general, poco recomendable. Existen programas y lenguajes de programacin
orientados a la gestin de bases de datos. Estos sistemas se encargan de gestionar el almacenamiento de informacin en disco y ofrecen utilidades para acceder y modificar la informacin. Es posible
expresar, por ejemplo, rdenes como busca todas las pelculas cuyo gnero es accin o lista a todos
los socios que llevan un retraso de 1 o ms das.
El lenguaje de programacin ms extendido para consultas a bases de datos es SQL (Standard
Query Language) y numerosos sistemas de bases de datos lo soportan. Existen, adems, sistemas
de bases de datos de distribucin gratuita como MySQL o Postgres, suficientemente potentes para
aplicaciones de pequeo y mediano tamao.
En otras asignaturas de la titulacin aprenders a utilizar sistemas de bases de datos y a disear
bases de datos.

Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

7.4.4.

Extensiones propuestas

Te proponemos como ejercicios una serie de extensiones al programa:

427
Modifica el programa para permitir que una pelcula sea clasificada en diferentes
gneros. (El atributo gnero ser una lista de cadenas, y no una cadena).

428
Modifica la aplicacin para permitir reservar pelculas a socios. Cuando de una
pelcula no se disponga de ningn ejemplar libre, los socios podrn solicitar una reserva.
Ojo!, la reserva se hace sobre una pelcula, no sobre un ejemplar, es decir, la lista de espera
de Matrix permite a un socio alquilar el primer ejemplar de Matrix que quede disponible. Por
otra parte, si hay, por ejemplo, dos socios con una misma pelcula reservada, solo podr alquilarse
a otros socios cuando haya tres o ms ejemplares libres.

429
Modifica el programa del ejercicio anterior para que las reservas caduquen automticamente a los dos das. Es decir, si el socio no ha alquilado la pelcula a los dos das, su
reserva expira.

430
Modifica el programa para que registre el nmero de veces que se ha alquilado cada
pelcula. Mediante una nueva opcin de men, el programa mostrar la lista de las 10 pelculas
ms alquiladas hasta el momento.

431
Modifica el programa para que registre todas las pelculas que ha alquilado cada
socio a lo largo de su vida. Al consultar los datos de un socio se mostrarn sus gneros favoritos.

432
Aade al programa una opcin de men para aconsejar al cliente. Basndose en su
historial de alquileres, el programa determinar sus gneros favoritos y mostrar un listado con
las pelculas de dichos gneros disponibles para alquiler.

7.4.5.

Algunas reflexiones

Hemos desarrollado un ejemplo bastante completo, pero lo hemos hecho poco a poco, incrementalmente. Hemos empezado por construir una aplicacin para un videoclub bsico y hemos ido
aadindole funcionalidad paso a paso. Normalmente no se desarrollan programas de ese modo.
Se parte de una especificacin de la aplicacin, es decir, se parte de una descripcin de lo que
debe hacer el programa. El programador efecta un anlisis de la aplicacin a construir. Un
buen punto de partida es determinar las estructuras de datos que utilizar. En nuestro caso,
hemos definido dos clases, Socio y Pelcula, y hemos decidido que mantendramos una lista de
socios y otra de pelculas como atributos de otra clase: Videoclub. Solo cuando se ha decidido
qu estructuras de datos utilizar se est en condiciones de disear e implementar el programa.
Pero ah no acaba el trabajo del programador. La aplicacin debe ser testeada para, en la
medida de lo posible, asegurarse de que no contiene errores. Solo cuando se est seguro de
que no los tiene, la aplicacin pasa a la fase de explotacin. Y es probable (o seguro!) que
entonces descubramos nuevos errores de programacin. Empieza entonces un ciclo de deteccin
y correccin de errores.
Tras un perodo de explotacin de la aplicacin es frecuente que el usuario solicite la implementacin de nuevas funcionalidades. Es preciso, entonces, proponer una nueva especificacin
(o ampliar la ya existente), efectuar su correspondiente anlisis e implementar las nuevas caractersticas. De este modo llegamos a la produccin de nuevas versiones del programa.

433
Nos gustara retomar el programa de gestin de
que desarrollamos en el ejercicio 400. Nos gustara introducir el concepto de lbum. Cada lbum tiene un ttulo, unos
intrpretes y una lista de canciones (ficheros
). Modifica el programa para que gestione
lbumes. Debers permitir que el usuario d de alta y baja lbumes, as como que obtenga
listados completos de los lbumes disponibles, listados ordenados por intrpretes, bsquedas de
canciones en la base de datos, etc.
Andrs Marzal / Isabel Gracia / Pedro Garca - ISBN: 978-84-697-1178-1

Introduccin a la programacin con Python 3 - UJI - DOI: http://dx.doi.org/10.6035/Sapientia93

ndice

434
Deseamos gestionar una biblioteca. La biblioteca contiene libros que los socios
pueden tomar prestados un nmero de das. De cada libro nos interesa, al menos, su ttulo, autor
y ao de edicin. De cada socio mantenemos su DNI, su nombre y su telfono. Un socio puede
tomar prestados tres libros. Si un libro tarda ms de 10 das en ser devuelto, el socio no podr
sacar nuevos libros durante un perodo de tiempo: tres das de penalizacin por cada da de
retraso.
Disea un programa que permita dar de alta y baja libros y socios y llevar control de los
prstamos y devoluciones de los libros. Cuando un socio sea penalizado, el programa indicar
por pantalla hasta qu fecha est penalizado e impedir que e