Python: Funciones

Una función es un fragmento de código con un nombre asociado que realiza una serie de tareas y devuelve un valor. A los fragmentos de código que tienen un nombre asociado y no devuelven valores se les suele llamar procedimientos. En Python no existen los procedimientos, ya que cuando el programador no especifica un valor de retorno la función devuelve el valor None, equivalente al null de Java.

Además de ayudarnos a programar y depurar dividiendo el programa en partes las funciones también permiten reutilizar código.

En Python las funciones se declaran de la siguiente forma:

def mi_funcion(param1, param2):
    print param1
    print param2

Es decir, la palabra clave def seguida del nombre de la función y entre paréntesis los argumentos separados por comas. A continuación, en otra línea, indentado y después de los dos puntos tendríamos las líneas de código que conforman el código a ejecutar por la función.

También podemos encontrarnos con una cadena de texto como primera línea del cuerpo de la función. Estas cadenas se conocen con el nombre de docstring (cadena de documentación) y sirven, como su nombre indica, a modo de documentación de la función.

def mi_funcion(param1, param2):
    """Esta funcion imprime los dos valores pasados
    como parametros"""
    print param1
    print param2

Al declarar la función lo único que hacemos es asociar un nombre al fragmento de código que conforma la función, de forma que podamos ejecutar dicho código más tarde referenciándolo por su nombre. Es decir, a la hora de escribir estas líneas no se ejecuta la función. Para llamar a la función (ejecutar su código) se escribiría:

mi_funcion("hola", 2)

Es decir, el nombre de la función seguido de los valores que queramos pasar como parámetros entre paréntesis. La asociación de los parámetros y los valores pasados a la función se hace normalmente de izquierda a derecha: como a param1 le hemos dado un valor “hola” y param2 vale 2, mi_funcion imprimiría hola en una línea, y a continuación 2.

Sin embargo también es posible modificar el orden de los parámetros si indicamos el nombre del parámetro al que asociar el valor a la hora de llamar a la función:

mi_funcion(param2 = 2, param1 = "hola")

El número de valores que se pasan como parámetro al llamar a la función tiene que coincidir con el número de parámetros que la función acepta según la declaración de la función. En caso contrario Python se quejará:

>>> mi_funcion(“hola”)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: mi_funcion() takes exactly 2 arguments (1 given)

También es posible no obstante definir funciones con un número variable de argumentos o bien asignar valores por defecto a los parámetros para el caso de que no se indique ningún valor para ese parámetro al llamar a la función.

Los valores por defecto para los parámetros se definen situando un signo igual después del nombre del parámetro y a continuación el valor por defecto:

def imprimir(texto, veces = 1):
    print veces * texto

En el ejemplo anterior si no indicamos un valor para el segundo parámetro se imprimirá una sola vez la cadena que le pasamos como primer parámetro:

>>> imprimir(“hola”)
hola

si se le indica otro valor, será este el que se utilice:

>>> imprimir(“hola”, 2)
holahola

Para definir funciones con un número variable de argumentos colocamos un último parámetro para la función cuyo nombre debe precederse de un signo ‘*’:

def varios(param1, param2, *otros):
    for val in otros:
        print otros

varios(1, 2)
varios(1, 2, 3)
varios(1, 2, 3, 4)

Esta sintaxis funciona creando una tupla (de nombre otros en el ejemplo) en la que se almacenan los valores de todos los parámetros extra pasados como argumento. Para la primera llamada, varios(1, 2), la tupla otros estaría vacía dado que no se han pasado más parámetros que los dos definidos por defecto, por lo tanto no se imprimiría nada. En la segunda llamada otros valdría (3), y en la tercera (3, 4).

También se puede preceder el nombre del último parámetro con ‘**’, en cuyo caso en lugar de una tupla se utilizaría un diccionario. Las claves de este diccionario serían los nombres de los parámetros indicados al llamar a la función y los valores del diccionario, los valores asociados a estos parámetros:

def varios(param1, param2, **otros):
    for i in otros.items():
        print i

varios(1, 2, tercero = 3)

Los que conozcáis algún otro lenguaje de programación os estaréis preguntando si en Python al pasar una variable como argumento de una función estas se pasan por referencia o por valor. En el paso por referencia lo que se pasa como argumento es una referencia o puntero a la variable, es decir, la dirección de memoria en la que se encuentra el contenido de la variable, y no el contenido en si. En el paso por valor, por el contrario, lo que se pasa como argumento es el valor que contenía la variable.

La diferencia entre ambos estriba en que en el paso por valor los cambios que se hagan sobre el parámetro no se ven fuera de la función, dado que los argumentos de la función son variables locales a la función que contienen los valores indicados por las variables que se pasaron como argumento. Es decir, en realidad lo que se le pasa a la función son copias de los valores y no las variables en si.

Si quisiéramos modificar el valor de uno de los argumentos y que estos cambios se reflejaran fuera de la función tendríamos que pasar el parámetro por referencia.

En C los argumentos de las funciones se pasan por valor, aunque se puede simular el paso por referencia usando punteros. En Java también se usa paso por valor, aunque para las variables que son objetos lo que se hace es pasar por valor la referencia al objeto, por lo que en realidad parece paso por referencia.

En Python también se utiliza el paso por valor de referencias a objetos, como en Java, aunque en el caso de Python, a diferencia de Java, todo es un objeto (para ser exactos lo que ocurre en realidad es que al objeto se le asigna otra etiqueta o nombre en el espacio de nombres local de la función).

Sin embargo no todos los cambios que hagamos a los parámetros dentro de una función Python se reflejarán fuera de esta, ya que hay que tener en cuenta que en Python existen objetos inmutables, como las tuplas, por lo que si intentáramos modificar una tupla pasada como parámetro lo que ocurriría en realidad es que se crearía una nueva instancia, por lo que los cambios no se verían fuera de la función.

Veamos un pequeño programa para demostrarlo:

def f(x, y):
    x = x + 3
    y.append(23)
    print x, y

x = 22
y = [22]
f(x, y)
print x, y

El resultado de la ejecución de este programa sería

25 [22, 23]

22 [22, 23]

Como vemos la variable x no conserva los cambios una vez salimos de la función porque los enteros son inmutables en Python. Sin embargo la variable y si los conserva, porque las listas son mutables.

En resumen: los valores mutables se comportan como paso por referencia, y los inmutables como paso por valor.

Con esto terminamos todo lo relacionado con los parámetros de las funciones. Veamos ahora cómo devolver valores, para lo que se utiliza la palabra clave return:

def sumar(x, y):
    return x + y

print sumar(3, 2)

Como vemos esta función tan sencilla no hace otra cosa que sumar los valores pasados como parámetro y devolver el resultado como valor de retorno.

También podríamos pasar varios valores que retornar a return.

def f(x, y):
    return x * 2, y * 2

a, b = f(1, 2)

Sin embargo esto no quiere decir que las funciones Python puedan devolver varios valores, lo que ocurre en realidad es que Python crea una tupla al vuelo cuyos elementos son los valores a retornar, y esta única variable es la que se devuelve.

Comentarios
  1. Oh yeah!!
    YA pensé que tenías abandonadillo el cursillo! 😀
    Mil gracias!

    Responder

  2. Muy buena info, gracias

    Responder

  3. ig

    Revisa el estilo del artículo ya que resulta poco coherente.
    Si es un curso para programadores en otros lenguajes explicar que es una función sobra y si el público objetivo son no programadores hablar del “null de java” es como mentar la “junta de la trócola”.

    Responder

  4. Es un tutorial para todos los lectores de Mundo geek interesados en aprender Python, sean o no programadores.

    Si no conoces otro lenguaje de programación basta con que ignores los comentarios sobre otros lenguajes. Si los conoces, es una ayuda para entender cómo funciona Python.

    Y viceversa, si sabes lo que es una función puedes ignorar su definición.

    Responder

  5. […] recurriendo a funciones con parámetros por defecto, a la sintaxis *params o **params explicada en Python: Funciones o bien usando decoradores (mecanismo que veremos más […]

    Responder

  6. […] variable de argumentos a un método de forma transparente, de la misma forma en que lo haríamos en otros lenguajes como Python. Basta añadir “…” después del […]

    Responder

  7. Manu Castro

    Hola, buenas. Me parece genial tu tutorial y sobretodo que compartas con todo el mundo tu conocimiento de python, creo que tu eres la persona indicada para resolver una cuestión que me trae algo de cabeza. Te comento: sabes como hacer una función swap (al estilo C)? en teoría todo lo de la mutabilidad está muy bien, pero no comprendo cómo nadie (ni siquiera Guido) explica una cosa que aparente es muy fácil caer en ella. Mira mi ejemplo:

    #prueba.py

    class Punto:
    pass

    def swap (a, b):
    a, b = b, a
    def principal ():
    p1 = Punto()
    p2 = Punto()
    print p1, p2
    swap(p1, p2)
    print p1, p2

    if __name__==”__main__”:
    principal () # esto lo hacemos para que los
    # objetos pasados no sean variables globales
    # del modulo

    Muchas gracias tío.

    Responder

  8. Manu Castro

    Perdón por no poner la identación , wl wordpress este es traicionero. 😉 Gracias nuevamente

    Responder

  9. @Manu Castro podrías meter ambos valores dentro de un diccionario, por ejemplo, que es mutable.

    O podrías devolver ambos valores y hacer a, b = swap(a, b).

    También puedes buscar en Google la implementación de un decorador que simulaba el paso por referencia.

    Responder

  10. Manuel Castro

    O sea que entiendo que aunque las clases creadas por el usuario sean mutables no se puede hacer swap de objetos creados a partir de ellas…Según observo tampoco se puede hacer para objetos lista (type = []), aunque también son mutables. Vamos que no se podía hacer era algo obvio, lo que no sabía es el porqué ….. De todas formas muchas gracias Raúl.

    Responder

  11. lionel

    Estoy haciendo un programa el cual lee un valores de un archivo

    def readconfig():

    f=open(“config.txt”)
    pc=f.readline(1)
    port=f.readline(2)
    print “el archivo de configuracion ha sido leido”, port
    f.close()
    return pc, port

    pero el port que esta en la linea 2 del archivo no
    es leída, me podrían ayudar no se cual sea mi error

    Responder

    • Amonino

      Prueba:

      f = open(“config.txt”, “r”)

      e.d.; añadiendo “r”

      Responder

  12. Israel

    Oye no se si lo mencionas pero lo que dices es una copia del libro “Python para todos”

    Responder

    • Python para todos es un libro escrito por mi, y está basado en estos artículos que fui escribiendo en su día en la bitácora. ¿No te has fijado en la URL del libro? 😉

      Responder

      • Remember

        Que crack!
        En su momento me baje tu libro en pdf para poder aprender de forma didactica phyton Pero ,por desgracia ,hacia falta mas conocimientos sobre el tema de los que yo tenia para poder empezar a leer el libro Asi que tube que recurrir a tutoriales y diversa informacion en internet Y me encontre con este excelente tutorial (http://pythonya.appspot.com/) ,que combinado con tu libro y un par de definiciones del wikipedia Me hicieron posible entender la programacion y ,como no, el lenguaje phyton Actualmente estoy empezando con java ,el cual se me esta haciendo mas facil que phyton Supongo que por conocer ,mas menos ,un lenguaje
        Bueno esto lo posteo como agradecimiento y que mas gente se animne a postear y a entrar en este mini universo

        Responder

  13. Ismael

    Es posible pasar una lista por valor a una función python?
    Estoy intentandoi hacer un programa que genera permutaciones de objetos en una lista, pero al llamar la funcion recursiva con la lista por parametro (valor), me modifica tambien la instancia de la lista en la función que llama.

    Responder

  14. andres

    Hola, tengo un problema.

    Yo estoy pasando este pedazo codigo de c++ a python.

    switch(cat)
    { case 1: desc=sub_total*0.05;
    total=sub_total-desc; break;

    case 2: desc=sub_total*0.08;
    total=sub_total-desc; break;

    case 3: desc=sub_total*0.12;
    total=sub_total-desc; break;

    case 4: desc=sub_total*0.15;
    total=sub_total-desc; break;

    default: cout<<"Categoria no valida;"; break;

    }

    pero no he podido, no se como simular el switch en python, intento con funciones pero al declarar las variables y realizar operaciones dentro de la funcion y no he podido.

    Me podrian ayudar.

    Responder

    • Anónimo

      Podrias hacerlo con if y elif.. Creo que es la forma mas sencilla de simular el Case.

      if (a = 5):
      return “Cinco”
      elif(a = 6):
      return “Seis”

      No se si a alguien se le ocurre otra forma. 🙂

      Con respecto al posteo la verdad que genial, super didactico.. :D. cuando sea grande quiero ser como vos.. ;).. de paso dejame publicitar mi blog que es nuevito.

      Gracias!

      Responder

    • Anónimo

      tipo=[0.05, 0.08, 0.12, 0.15]
      if cat>4 or cat<1:
      print "Categoría no valida"
      else
      desc=sub_total*tipo[cat-1]

      Responder

      • Anónimo

        Se comió toda la identación

        Responder

        • Anónimo

          Para algo más complejo puedes emplear un diccionario donde las claves son los posibles valores de cat y los valores posibles funciones a implementar.
          Si el valor está entre las claves se obtiene la función y se ejecuta; en caso contrario se visualiza el mensaje de error.

          Responder

  15. sssssssssssssssssssssss

    Responder

  16. Anónimo

    Para este ejemplo en particular no implementaría un switch.
    switch(cat)
    { case 1: desc=sub_total*0.05;
    total=sub_total-desc; break;

    case 2: desc=sub_total*0.08;
    total=sub_total-desc; break;

    case 3: desc=sub_total*0.12;
    total=sub_total-desc; break;

    case 4: desc=sub_total*0.15;
    total=sub_total-desc; break;

    default: cout<4 or cat4 or cat<1:
    print "Categoría no valida"
    else
    total=sub_total*(1-tipo[cat-1])

    Responder

  17. fiofarinasso

    Está excelente tu tutorial estaría buenísimo lo pudieras completar.. buenísimos aportes–

    Responder

  18. DYDG

    Me podrían decir como puedo hacer este programa en Python. Por favor.

    este es el nombre de la función: examen(lista_respuestas):
    Regresa calificación
    Escribe una función que recibe la lista con las respuestas (A,B,C,D) del número de preguntas que se deseen y de acuerdo a este número le preguntará al usuario su respuesta a cada pregunta. La función llevará el conteo de los aciertos y calculará la calificación, este último valor lo regresará.

    Responder

  19. Teresa

    No se como crear una función que reciba un parámetro que sea n! y retorne el factorial de ese nº, alguien podría ayudarme?

    Gracias

    Responder

  20. ezequiel

    gracias,
    buenos tutos en mundo geek

    Responder

  21. cheko

    https://www.facebook.com/groups/356741544428669/

    este es un grupo para programadores en python des de los que quieren aprender hasta los mas expertos
    para aclararnos dudas,compartir códigos,librerias, etc

    Responder

  22. a mi me parece que tenia q ser con funciones no con lo basico sino con lo complicado

    Responder

  23. Anthony

    La verdad,su informacíon no me ayudado en nada ..hola..

    Responder

  24. Elba Cilon

    Gracias x la info

    Responder

  25. caniche

    exelente gracias

    Responder

Deja un comentario