Subsecciones


4. M�s herramientas de control de flujo

Adem�s de la sentencia while, reci�n presentada, Python conoce las sentencias de control de flujo comunes de otros lenguajes, aunque con sabor propio.


4.1 Construcciones if

Quiz� la mejor conocida de las construcciones es if (si). Por ejemplo:

>>> x = int(raw_input("Introduce un n�mero: "))
>>> if x < 0:
...      x = 0
...      print 'Negativo cambiado a cero'
... elif x == 0:
...      print 'Cero'
... elif x == 1:
...      print 'Uno'
... else:
...      print 'M�s'
...

Puede haber cero o m�s partes elif y la parte else (si no) es opcional. La palabra clave `elif' es una abreviatura de `else if' y evita el sagrado excesivo. Una secuencia if ... elif ... elif ... es el sustituto de las sentencias switch o case de otros lenguajes.


4.2 Sentencias for

La construcci�n for (para) es un poco diferente a lo acostumbrado en C o Pascal. En lugar de recorrer siempre una progresi�n aritm�tica (como en Pascal) o dejar al programador total libertad de elecci�n de inicializaci�n, comprobaci�n y salto de paso (como en C), el for de Python recorre los elementos de una secuencia (por ejemplo, una lista o cadena), en el orden en que aparecen en la secuencia. Por ejemplo:

>>> # Medir algunas cadenas:
... a = ['gato', 'ventana', 'defenestrar']
>>> for x in a:
...     print x, len(x)
... 
gato 4
ventana 7
defenestrar 11

No es aconsejable modificar la secuencia que se est� recorriendo (lo que s�lo puede ocurrir en secuencias mutables, por ejemplo, listas). Si se necesita modificar la lista recorrida, por ejemplo, para duplicar los elementos, hay que recorrer una copia. La notaci�n de corte hace esto muy c�modo.

>>> for x in a[:]: # hacer una copia por corte de la lista entera
...    if len(x) > 7: a.insert(0, x)
... 
>>> a
['defenestrar', 'gato', 'ventana', 'defenestrar']


4.3 La funci�n range()

Si lo que necesitas es recorrer una secuencia de n�meros, la funci�n interna range() viene de perlas. Genera listas con progresiones aritm�ticas, por ejemplo:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

El punto final indicado nunca es parte de la lista generada, as� que range(10) genera una lista de 10 valores, justo los �ndices legales de los elementos de una secuencia de longitud 10. Es posible hacer que el rango arranque en otro n�mero o especificar un incremento diferente (incluso negativo). Este incremento se llama paso (step):

>>> range(5, 10)
[5, 6, 7, 8, 9]
>>> range(0, 10, 3)
[0, 3, 6, 9]
>>> range(-10, -100, -30)
[-10, -40, -70]

Para recorrer los �ndices de una secuencia, combina range() y len() de este modo:

>>> a = ['Cinco', 'lobitos', 'tiene', 'la', 'loba']
>>> for i in range(len(a)):
...     print i, a[i]
... 
0 Cinco
1 lobitos
2 tiene
3 la
4 loba


4.4 Construcciones con break, continue y else en bucles

La sentencia break (romper), como en C, salta del bucle for o while en curso m�s interno.

La sentencia continue (continuar), tambi�n un pr�stamo de C, hace que siga la siguiente iteraci�n del bucle.

Las construcciones de bucle pueden tener una cl�usula else. �sta se ejecuta, si existe, cuando se termina el bucle por agotamiento de la lista (con for) o cuando la condici�n se hace falsa (con while), pero no cuando se termina el bucle con break. Para aclarar esto �ltimo, valga un ejemplo, que busca n�meros primos:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...            print n, '=', x, '*', n/x
...            break
...     else:
...          print n, 'es primo'
... 
2 es primo
3 es primo
4 = 2 * 2
5 es primo
6 = 2 * 3
7 es primo
8 = 2 * 4
9 = 3 * 3


4.5 Construcciones con pass

La sentencia pass no hace nada. Se puede utilizar cuando hace falta una sentencia sint�cticamente pero no hace falta hacer nada. Por ejemplo:

>>> while 1:
...       pass # Espera activamente una interrupci�n de teclado
...


4.6 Definici�n de funciones

Se puede crear una funci�n que escriba la serie de Fibonacci hasta un l�mite superior arbitrario:

>>> def fib(n):    # escribir la serie Fibonacci hasta n
...     "escribir la serie Fibonacci hasta n"
...     a, b = 0, 1
...     while b < n:
...         print b,
...         a, b = b, a+b
... 
>>> # Y ahora llamamos a la funci�n reci�n definida:
... fib(2000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

La palabra clave def introduce una definici�n de funci�n. Debe ir seguida del nombre de la funci�n y la lista entre par�ntesis de los par�metros formales. Las sentencias que forman el cuerpo de la funci�n empiezan en la siguiente l�nea y deben ir sangradas. La primera sentencia del cuerpo de la funci�n puede ser una constante de cadena: esta cadena es la documentaci�n de la funci�n o docstring.

Existen herramientas para producir autom�ticamente documentaci�n impresa/electr�nica o permitir al usuario navegar por el c�digo interactivamente. Es una buena pr�ctica incluir documentaci�n en el c�digo que escribas, as� que intenta hacer de ello un h�bito.

La ejecuci�n de una funci�n introduce una tabla de s�mbolos nueva para las variables locales de Python. En concreto, todas las asignaciones de variables de una funci�n almacenan el valor en la tabla de s�mbolos local; por lo que las referencias a variables primero miran en la tabla de s�mbolos local, luego en la tabla de s�mbolos global y, por �ltimo, en la tabla de nombres internos. Por ello no se puede asignar un valor a una variable global dentro de una funci�n (salvo que est� mencionada en una sentencia global), pero se puede hacer referencia a ellas.

Los par�metros reales (argumentos) de una llamada a una funci�n se introducen en la tabla de s�mbolos local de la funci�n aludida al llamarla: los argumentos se pasan por valor (en donde el valor siempre es una referencia a un objeto, no el valor del objeto4.1. Cuando una funci�n llama a otra funci�n, se crea una tabla de s�mbolos locales nueva para esa llamada.

Una definici�n de funci�n introduce el nombre de la funci�n en la tabla de s�mbolos vigente. El valor del nombre de la funci�n tiene un tipo reconocido por el int�rprete como funci�n definida por el usuario. Se puede asignar este valor a otro nombre y usar �ste, a su vez, como funci�n que es. Esto sirve de mecanismo de renombrado gen�rico:

>>> fib
<function object at 10042ed0>
>>> f = fib
>>> f(100)
1 1 2 3 5 8 13 21 34 55 89

Se puede objetar que fib no es una funci�n, sino un procedimiento. En Python, como en C, los procedimientos son simplemente funciones que no devuelven ning�n valor. De hecho, hablando t�cnicamente, los procedimientos s� devuelven un valor, s�lo que bastante aburrido. Este valor se llama None (es un nombre interno). El int�rprete suele omitir la escritura del valor de None, si es el �nico valor que se fuera a escribir. Se puede ver si realmente lo deseas:

>>> print fib(0)
None

Resulta simple escribir una funci�n que devuelva una lista de los n�meros de la serie de Fibonacci, en lugar de mostrarla:

>>> def fib2(n): # Devolver la serie de Fibonacci hasta n
...     "Devolver una lista con los n�meros de la serie de Fibonacci hasta n"
...     resultado = []
...     a, b = 0, 1
...     while b < n:
...         resultado.append(b)    # ver m�s abajo
...         a, b = b, a+b
...     return resultado
... 
>>> f100 = fib2(100)    # llamarlo
>>> f100                # escribir el resultado
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
Este ejemplo, como es habitual, demuestra algunas caracter�sticas nuevas de Python:


4.7 M�s sobre la definici�n de funciones

Tambi�n es posible definir funciones con un n�mero variable de argumentos. Existen tres formas, que se pueden combinar.


4.7.1 Valores por omisi�n en los argumentos

Es la forma m�s �til de especificar un valor por omisi�n para uno o m�s de los argumentos. Esto crea una funci�n a la que se puede llamar con menos argumentos de los que tiene definidos, por ejemplo:

def confirmar(indicador, intentos=4, queja='�O s� o no!'):
    while 1:
        respuesta = raw_input(indicador)
        if respuesta in ('s', 'si', 's�'): return 1
        if respuesta in ('n', 'no', 'nanay', 'nasti'): return 0
        intentos = intentos - 1
        if intentos < 0: raise IOError, 'Usuario rechazado'
        print queja

Se puede llamar a esta funci�n as�: confirmar('�Quiere salir?') o as�: confirmar('�Desea borrar el fichero?', 2).

Los valores por omisi�n se eval�an en el instante de definici�n de la funci�n en el �mbito de definici�n, as�:

i = 5
def f(arg = i): print arg
i = 6
f()

mostrar� 5.

Aviso importante: El argumento por omisi�n se eval�a una sola vez. Esto lleva a diferentes resultados cuando el valor por omisi�n es un objeto mutable, tal como una lista o diccionario. Por ejemplo, la siguiente funci�n acumula los argumentos que se le pasan en sucesivas llamadas:

def f(a, l = []):
    l.append(a)
    return l
print f(1)
print f(2)
print f(3)

Esto presenta:

[1]
[1, 2]
[1, 2, 3]

Si no se desea que el valor por omisi�n sea compartido por las sucesivas llamadas, se puede escribir la funci�n de este modo:

def f(a, l = None):
    if l is None:
        l = []
    l.append(a)
    return l


4.7.2 Argumentos por clave

Tambi�n se puede llamar a una funci�n utilizando la forma "clave = valor". Por ejemplo, la siguiente funci�n:

def loro(tension, estado='tieso', accion='voom', tipo='Azul noruego'):
    print "-- Este loro no podr�a", accion,
    print "aunque le aplicara", tension, "voltios."
    print "-- Bello plumaje, el", tipo
    print "-- �Est�", estado, "!"

puede invocarse de estas maneras:

loro(1000)
loro(accion = 'VOOOOOM', tension = 1000000)
loro('mil', estado = 'criando malvas')
loro('un mill�n de', 'desprovisto de vida', 'saltar')

pero las siguientes llamadas ser�an todas incorrectas:

loro()                       # falta un argumento obligatorio
loro(tension=5.0, 'muerto')  # argumento clave seguido por argumento no-clave
loro(110, tension=220)       # valor de argumento duplicado 
loro(actor='John Cleese')    # clave desconocida

En general, una lista de argumentos debe tener argumentos posicionales seguidos por argumentos clave, donde las claves se seleccionan de los nombres de los par�metros formales. No importa si un par�metro formal tiene valor por omisi�n o no. Ning�n argumento debe recibir valor m�s de una vez (los nombres de par�metros formales correspondientes a argumentos posicionales no se pueden usar como claves en la misma llamada). He aqu� un ejemplo que falla por culpa de esta restricci�n:

>>> def function(a):
...     pass
... 
>>> function(0, a=0)
Traceback (innermost last):
  File "<stdin>", line 1, in ?
TypeError: keyword parameter redefined

Cuando el �ltimo par�metro formal tiene la forma **nombre recibe un diccionario que contiene todos los argumentos clave cuya clave no se corresponde con ning�n par�metro formal. Esto se puede combinar con un par�metro formal de la forma *nombre (descrito en la siguiente subsecci�n) que recibe una tupla que contiene los argumentos posicionales que exceden la lista de par�metros formales (*nombre debe aparecer antes de **nombre). Por ejemplo, si definimos una funci�n como �sta:

def queseria(clase, *argumentos, **claves):
    print "-- �Tiene", clase, '?'
    print "-- Lo siento, no nos queda", clase
    for arg in argumentos: print arg
    print '-'*40
    for kw in claves.keys(): print kw, ':', claves[kw]

se puede invocar de estas maneras:

queseria('Limburger', "Chorrea mucho, se�or.",
           "Chorrea mucho, much�simo.",
           cliente='John Cleese',
           tendero='Michael Palin',
           sketch='Sketch de la queser�a')

Y mostrar�a:

-- �Tiene Limburger ?
-- Lo siento, no nos queda Limburger
Chorrea mucho, se�or.
Chorrea mucho, much�simo.
----------------------------------------
cliente : John Cleese
tendero : Michael Palin
sketch : Sketch de la queser�a


4.7.3 Listas de argumentos arbitrarias

Finalmente, la opci�n menos frecuente es especificar que una funci�n puede llamarse con un n�mero arbitrario de argumentos. Estos argumentos se agrupar�n en una tupla. Antes del n�mero variable de argumentos puede haber cero o m�s argumentos normales.

def fprintf(file, formato, *args):
    file.write(formato % args)


4.7.4 Formas lambda

A petici�n popular, se han a�adido a Python algunas caracter�sticas com�nmente halladas en los lenguajes de programaci�n funcional y Lisp. Con la palabra clave lambda es posible crear peque�as funciones an�nimas. �sta es una funci�n que devuelve la suma de sus dos argumentos: "lambda a, b: a+b". Las formas lambda se pueden utilizar siempre que se necesite un objeto funci�n. Est�n sint�cticamente restringidas a una expresi�n simple. Sem�nticamente son un caramelo sint�ctico para una definici�n de funci�n normal. Al igual que las definiciones de funciones anidadas, las formas lambda no pueden hacer referencia a las variables del �mbito que las contiene, aunque esto se puede subsanar mediante el uso juicioso de los valores de argumento por omisi�n, por ejemplo:

def montar_incrementador(n):
    return lambda x, incr=n: x+incr


4.7.5 Cadenas de documentaci�n

Hay convenciones crecientes sobre el contenido y formato de las cadenas de documentaci�n.

La primera l�nea debe ser siempre un corto y conciso resumen de lo que debe hacer el objeto. En aras de la brevedad, no debes hacer constar el nombre y tipo del objeto, pues �stos est�n disponibles mediante otros modos (excepto si el nombre es un verbo que describe el funcionamiento de la funci�n). Esta l�nea debe empezar por may�scula y terminar en punto.

Si hay m�s l�neas en la cadena de documentaci�n, la segunda l�nea debe ir en blanco, separando visualmente el resumen del resto de la descripci�n. Las siguientes l�neas deben ser p�rrafos que describan las convenciones de llamada de los objetos, sus efectos secundarios, etc.

El analizador de Python no elimina el sangrado de los literales multil�nea, as� que las herramientas que procesen documentaci�n tienen que eliminar el sangrado si se desea. Esto se realiza del siguiente modo. La primera l�nea que no est� en blanco tras la primera l�nea de la documentaci�n determina el grado de sangrado de la cadena de documentaci�n entera (no se puede utilizar la primera l�nea, porque suele estar pegada a las comillas de apertura y su sangrado no es evidente dentro del literal). Se elimina el espacio en blanco ``equivalente'' a este sangrado del principio de todas las l�neas de la cadena. No deber�a haber l�neas menos sangradas, pero si las hay se debe eliminar su espacio en blanco inicial. La equivalencia del espacio en blanco se debe realizar tras la expansi�n de los tabuladores (a 8 espacios, normalmente).

He aqu� un ejemplo de una cadena de documentaci�n multil�nea:

>>> def mi_funcion():
...     """No hacer nada, pero comentarlo muy bien.
... 
...     Que no, que no hace nada.
...     """
...     pass
... 
>>> print mi_funcion.__doc__
No hacer nada, pero comentarlo muy bien.

    Que no, que no hace nada.



Notas al pie

... objeto4.1
En realidad, por referencia al objeto resultar�a m�s correcto, ya que si se pasa un objeto mutable, el que llama ver� los cambios realizados por el llamado (por ejemplo, si inserta elementos en una lista).

Ver Sobre este documento... para obtener informaci�n sobre sugerencias.