Funciones


Una función en Python es un fragmento de código que se ejecuta cada vez que es invocado. El concepto es muy útil cuando quieres que se realice la misma tarea en diferentes partes de un programa (ya que de esta forma sólo lo tienes que escribirlo en un sitio y no en todos) o a efectos de modificar o ampliar tu código.
Las funciones te permiten organizarte mejor y estructurar el código de una manera saludable.
Su sintaxis más simple es la siguiente:
def nombreFunción():
    ......
    instrucciones de la función
    ......
Como se ve, es un bloque y por tanto todas las instrucciones que forman la función deben estar sangradas. El bloque se inicia con def y se sigue con el nombre que queremos darle a la función (con las mismas restricciones que los nombres de variables ). A continuación los paréntesis y los dos puntos que marcan el inicio del contenido del bloque.
Para llamar a la función, escribimos simplemente su nombre (incluyendo los paréntesis):
....
nombreFunción()
....
Veamos un ejemplo:
def saluda():
    print "Hola"
 
print "Voy a saludar"
saluda()
print "Y voy a saludar otra vez"
saluda()
Cuando se ejecuta el código anterior, se imprime en pantalla lo siguiente:
Voy a saludar
Hola
Y voy a saludar otra vez
Hola
¿Ventajas? Si, por ejemplo decido cambiar el saludo, sólo tengo que modificarlo en la definición de la función. Si no lo hubiera hecho con una función, usando dos print más, tendría que modificar esos dos print.

Las funciones también admiten parámetros. Fíjate la siguiente función:
def saluda(nombre):
    print "Hola, " + nombre
Y, ahora, fíjate en lo que sucede:
>>> saluda('Carlos')
'Hola, Carlos'
Cuando defino una función con un nombre entre paréntesis (parámetro) puedo usarlo dentro de ella para manipularla como si fuera una variable. El nombre que elijamos en realidad da lo mismo, así que usa nombres que signifiquen algo para ti. Cuando invoquemos a la función, hay que darle un valor entre paréntesis, que será el valor que use Python para ejecutar la función.
En el ejemplo, llamamos a la función con el valor 'Carlos', que es una string . Cuando Python ejecuta la función automáticamente la hace corresponder con la variable nombre y, por tanto, el print devuelve 'Hola, Carlos'.
¡Cuidado! Python no verifica por ti que los tipos de datos sean los correctos. Podías haber escrito perfectamente saluda(33) y Python lo habría aceptado, pero al ejecutar la función, devolvería un error puesto que la instrucción print "Hola, " + nombre no puede hacerse ya que nombre sería 33 y no un texto. Este tipo de errores son habituales y un quebradero de cabeza para los programadores que deben asegurarse que todo es correcto.
Otro ejemplo sencillo, esta vez con dos parámetros:
def suma(a,b):
    c = a + b
    print "La suma vale..."
    print c
 
Si ahora llamamos a la función de la siguiente manera:
suma(3,5)
El resultado de la ejecución será:
La suma vale...
8
Las funciones también pueden devolver valores con la instrucción return. En ese caso, hay que hacer algo con el valor que se devuelve. Muchas veces lo que harás será almacenar dicho valor en una variable. En este sentido, el ejemplo anterior también podrías conseguirlo de esta otra forma:
def suma(a,b):
    return a + b
 
print "La suma vale..."
print suma(3,5)
La definición de la función simplemente dice que ésta devuelve la suma de los dos valores que se le pasan como parámetros. El resto del programa es su ejecución: Primero escribe 'La suma vale...' y a continuación escribe el resultado que devuelve la función (de hecho, Python lo que hace es sustituir suma(3,5) por el valor que devuelve la función, 8).
Finalmente, también puede usarse sin ningún valor, una forma útil de provocar la salida de la función en cualquier punto de su definición. Fíjate en el siguiente ejemplo, en el que usaremos un bucle infinito y forzamos la salida de la función cuando la cuenta llega a 10:
>>>def cuenta10():
    i=0
    while True:
        i = i + 1
        if i == 10:
            return

Argumentos


Como has comprobado, las funciones pueden llevar argumentos, valores que son utilizados luego en las funciones. Estos argumentos, al definirse, pueden ser "especiales"...

>>>def saluda(*nombre):
...    for i in nombre:
...        print "Hola, " + i

De momento ignora el asterisco... si ponemos un nombre, el resultado será:
>>>saluda('Juan')
Hola, Juan

Y ahora, pogamos varios nombres, separados por comas...
>>>saluda('Juan', 'Pedro', 'Carlos')
Hola, Juan
Hola, Pedro
Hola, Carlos

¿Lo has visto? Con el asterisco, Python interpreta los nombres que separábamos con comas como una tupla (como recordarás, una forma abreviada de crear tuplas, es escribir elementos separados por comas).

Si queremos añadir otros argumentos distintos, el argumento "plural" debe ir al final:
>>>def saluda(nombreEspecial ,*nombre):
...    for i in nombre:
...     print "Hola, " + i
...
...    print "Buenas tardes, " + nombreEspecial
>>>saluda('Fernando','Juan', 'Pedro', 'Carlos')
Hola, Juan
Hola, Pedro
Hola, Carlos
Buenas tardes, Fernando

También podemos hacerlo al revés, usando el asterisco al llamar la función y dar los valores:
>>>def saluda(nombre1 ,nombre2, nombre3):
...    print "Hola, " + nombre1
...    print "Buenas tardes, " + nombre2
...    print "Luego nos vemos, " + nombre3
...
>>>amigos = ('Fernando', 'Juan')
>>>
>>>saluda('Marcos', *amigos)
Hola, Fernando
Buenas tardes, Juan
Luego nos vemos, Marcos
(Por cierto, a esta clase de argumentos se les conoce como *args.)


También podemos crear diccionarios, usando ahora el doble asterisco. Esto se conoce como la forma "keyworded" (y se les llama **kwargs):
>>> def nombre_empleados(**empleados):
...     print empleados
>>>nombre_empleados(Secretaria='Marta', Contable='Marcos', Jefe='Pedro')
{'Contable': 'Marcos', 'Secretaria': 'Marta', 'Jefe': 'Pedro'}

Y al igual que con los args, se puede realizar la forma "invertida", como veíamos en la función "saluda":
>>> def numeritos(number1, number2, number3):
...     print number1
...     print number2
...     print number3
 
>>> kwargs = {"number2": 10, "number3": "cuarenta y dos"}
>>> numeritos('3,14', **kwargs)
3,14
10
cuarenta y dos

Finalmente, están los argumentos predefinidos, en los que el argumento se puede omitir, por lo que Python usará un argumento ya descrito por nosotros, algo extremadamente útil:

>>> def saluda(nombre, sexoMasculino=True):
...     if sexoMasculino:
...         print 'Buenas noches sir ' + nombre
...     if not sexoMasculino:
...         print 'Buenas noches lady ' + nombre
 
>>> saluda('Bradbury')
Buenas noches sir Bradbury
>>> saluda('Lovelace', False)
Buenas noches lady Lovelace