post

Python sp-ar:Funciones

Contents

Introducción

Las funciones son piezas de programas reusables, que nos permiten darle un nombre a un bloque de instrucciones, para ejecutar este desde cualquier parte del programa el numero de veces que queramos. Esto es conocido como llamar la función y ya lo hemos hecho con muchas de las funciones que vienen incluidas en Python como len y range.

El concepto de función es probablemente el bloque de construcción mas importante de cualquier software no trivial (en cualquier lenguaje de programación), entonces en este capitulo exploraremos varios aspectos de las funciones.

Las funciones son definidas usando la palabra clave def, después de esta viene nombre identificador para la función seguido por un par de paréntesis los cuales pueden encerrar algunos nombres de variables y al final un dos puntos para terminar la linea. Después de esto sigue el bloque de instrucciones que conforman la función. A continuación voy a mostrar un ejemplo realmente muy simple:

Ejemplo:

#!/usr/bin/python
# Archivo: function1.py

def saludar():
    print('Hola Mundo!') # bloque que pertenece a la función
# Final de la función

saludar() # se llama la función
saludar() # se llama la función otra vez

Salida:

   $ python function1.py
   Hola Mundo!
   Hola Mundo!

Como Funciona:

Usando la sintaxis que se explico con anterioridad definimos la función saludar, la cual no toma parámetros y por lo tanto no se declaran variables en los paréntesis. Los parámetros solo son solo una entrada que las funciones necesitan para hacer su trabajo y según los diferentes valores que pasemos nos regresaran los resultados correspondientes.

Observe que nosotros llamamos la misma función dos veces, lo que significa que no tenemos que escribir el mismo código de nuevo.

Parámetros de Funciones

Una función puede tomar parámetros, los cuales son valores que se le suministran para que esta haga algún trabajo utilizándolos. Los parámetros son como variables excepto que estos son definidos cuando se llama a la función y son asignados realmente cuando se ejecuta la función.

Los parámetros son especificados entre un par de paréntesis y separados por comas en la definición de la función, cuando llamamos a una función los valores se los suministramos de la misma manera que están en la definición. observe la terminología que se usa – los nombres que damos en la definición de la función son llamados parámetros mientras que los valores que suministramos cuando llamamos a la función son los argumentos.

Ejemplo:

#!/usr/bin/python
# Archivo: func_param.py

def imprimirMayor(a, b):
    if a > b:
        print(a, 'es mayor')
    elif a == b:
        print(a, 'es igual', b)
    else:
        print(b, 'es mayor')

imprimirMayor(3, 4) # le pasamos directamente valores literales

x = 5
y = 7

imprimirMayor(x, y) # le pasamos variables como argumentos

Salida:

   $ python func_param.py
   4 es mayor
   7 es mayor

Como Funciona:

Aquí, hemos definido una función llamada imprimirMayor la cual usa dos parámetros llamados a y b además encuentra el mayor usando una simple instrucción if..else para luego imprimirlo.

La primer vez que llamamos la función imprimirMayor, directamente suministramos los números como argumentos pero la segunda vez que llamamos la función le pasamos variables como argumentos. imprimirMayor en su definición determina que el valor de los argumentos x y y sean asignado a los parámetros a y b respectivamente también para el otro caso funciona de la misma forma.

Variables Locales

Cuando declaramos variables en el interior de una función, estas no se relacionan de ninguna manera con variables que usen el mismo nombre fuera de esta, es decir las variables son locales de la función. Esto es llamado el ámbito de variable. Todas las variables tienen el ámbito del bloque donde fueron declaradas y empieza desde el momento de la definición de su nombre.

Ejemplo:

#!/usr/bin/python
# Archivo: func_local.py

x = 50

def func(x):
    print('x es', x)
    x = 2
    print('Se cambia x local a', x)

func(x)
print('x sigue siendo', x)

Salida:

   $ python func_local.py
   x es 50
   Se cambia x local a 2
   x sigue siendo 50

Como Funciona:

Cuando por primera vez imprimimos el valor de la variable x en la primer linea del cuerpo de la función, Python usa el valor del parámetro declarado en el bloque principal, sobre la definición de la función.

Pero enseguida, asignamos el valor de 2 a x, la cual es una variable local de la función. Entonces cuando cambiamos el valor de x en la función, la x definida en el bloque principal permanece inalterada.

Con el ultimo llamado a la función print, imprimimos el valor de x definido en el bloque principal, así comprobamos que esta realmente no fue alterada por la asignación que se hizo en el aterir llamado a función.

Usando la Instrucción global

Si queremos declarar una variable en lo mas alto del programa (es decir por fuera de cualquier tipo de ámbito como funciones o clases), entonces tenemos que decirle a Python que la variable no es local, pero si es global. Para hacer esto usamos la instrucción global, sin esta seria imposible asignar un valor a una variable definida fuera de una función.

Usted puede utilizar los valores de estas variables definidas fuera de la función (asumiendo que no hay otra variable dentro de la función con el mismo nombre). Sin embargo esto no es recomendado y debería ser evitado porque para el lector de el programa se vuelve poco claro donde es definida la variable. Es claro que usando la instrucción global‘ la variable se define en el bloque más exterior del programa.

Ejemplo:

#!/usr/bin/python
# Archivo: func_global.py

x = 50

def func():
    global x

    print('x es', x)
    x = 2
    print('Se cambia x global por', x)

func()
print('El valor de x es', x)

Salida:

   $ python func_global.py
   x es 50
   Se cambia x global por 2
   El valor de x es 2

Como Funciona:

La instrucción global es usada para declarar que x es una variable global – y por lo tanto, cuando le asignamos un valor a x dentro de la función, el cambio se ve reflejado en la x del bloque principal.

Se puede declarar mas de una variable global usando la misma instrucción global, por ejemplo: global x, y, z

Usando la Instrucción nonlocal

Anteriormente hemos visto como acceder a variables en el ámbito local y global, pero hay otro tipo de ámbito llamado “no local” (nonlocal scope) el cual está entre los dos anteriores ámbitos. Este es observado cuando se definen funciones dentro de funciones

Ya que todo en Python es solo código ejecutable, se puede definir funciones en cualquier parte.

Veamos un ejemplo:

#!/usr/bin/python
# Archivo: func_nonlocal.py

def func_exterior():
    x = 2
    print('x es', x)

    def func_interior():
        nonlocal x
        x = 5

    func_interior()
    print('Se cambia x local a', x)

func_exterior()

Salida:

   $ python func_nonlocal.py
   x es 2
   Se cambia x local a 5

Como Funciona:

Cuando estamos dentro de func_interior, la variable x que se definió en la primera linea de func_exterior no es ni del ámbito local (la definición de la variable no hace parte del bloque de func_interior) ni del ámbito global (tampoco esta en el bloque principal). Entonces para acceder esa especifica x usaremos nonlocal x.

Intente cambiar nonlocal x por global x, y luego quite la instrucción completa y observe la diferencia en comportamiento de esos dos casos.

Valores de Argumentos por Defecto

Para algunas funciones, puede que quiera hacer algunos parámetros opcionales y usar valores por defecto en caso de que el usuario no provea valores para ellos. Esto se puede lograr con la ayuda de valores de argumentos por defecto. Usted puede especificar un valor de un argumento por defecto con solo añadirle al nombre del parámetro en la definición de la función el operador de asignación (=) seguido del valor por defecto.

El valor de argumento por defecto debe ser una constante, mas exactamente este debe ser inmutable – esto se explica en detalle en capítulos posteriores. Por ahora, solo tenga en cuenta esto.

Ejemplo:

#!/usr/bin/python
# Archivo: func_default.py

def decir(mensaje, veces = 1):
    print(mensaje * veces)

decir('Hola')
decir('Mundo', 5)

Salida:

   $ python func_default.py
   Hola
   MundoMundoMundoMundoMundo

Como Funciona:

La función llamada decir es usada para imprimir una cadena de caracteres (string) tantas veces como se especifique, pero si nosotros no suministramos un valor entonces, por defecto la cadena se imprime solo una vez. Esto lo logramos porque especificamos que 1 es el valor de argumento por defecto del parámetro veces.

Cuando usamos por primera vez decir, solo suministramos la cadena, entonces este solo la imprimirá una vez, pero la segunda vez nosotros pasamos ambos la cadena y el argumento 5 declarando que queremos decir la cadena 5 veces.

Importante
Solo los parámetros que están al final de la lista de parámetros pueden tener valores de argumentos por defecto, es decir que en la lista de parámetros de de una función no se puede tener un parámetro con un argumento por defecto precediendo un parámetro sin un valor de argumento por defecto.
Esto es debido a que los valores de los parámetros se asignan por su posición. Por ejemplo def func(a, b=5) es valida, pero def func(a=5, b) no es valida.

Argumentos por Palabra Clave

Si tiene algunas funciones con muchos parámetros y quiere solo especificar algunos de ellos, entonces puede darle valores a estos parámetros nombrándolos – esto es llamado argumentos por palabra clave (keyword arguments) – nosotros usamos el nombre (palabra clave) en ves de la posición (que hemos estado usando todo este tiempo) para pasar los argumentos a la función.

Existen dos ventajas – uno, usar la funciona es mas fácil ya que no nos tenemos que preocupar por el orden de los argumentos. Dos, le podemos dar valores solo a los argumentos que queremos, siempre y cuando los otros parámetros tengan valores de argumentos por defecto.

Ejemplo:

#!/usr/bin/python
# Archivo: func_key.py

def func(a, b=5, c=10):
    print('a es', a, 'y b es', b, 'y c es', c)

func(3, 7)
func(25, c=24)
func(c=50, a=100)

Salida:

   $ python func_key.py
   a es 3 y b es 7 y c es 10
   a es 25 y b es 5 y c es 24
   a es 100 y b es 5 y c es 50

Como Funciona:

La función llamada func tiene un parámetro sin un valor de argumento por defecto seguido de dos parámetros con argumentos por defecto.

Cuando se usa por primera vez func(3, 7), el parámetro a guarda el valor 3, b guarda el valor 7 y c guarda el valor por defecto 10.

En el segundo uso func(25,c=24), la variable a guarda el valor 25 debido a la posición del argumento, luego el parámetro c guarda el valor 24 debido a la asignación por nombre, es decir, argumentos por palabra clave y la variable b guarda el valor por defecto de 5.

En el tercer uso func(c=50, a=100), usamos argumentos por palabra clave para especificar todos lo valores. Observe que especificamos el valor para el parámetro c antes del valor para el parámetro a, incluso aunque a esta declarada antes que c en la definición de la función.

Parámetros VarArgs

Pendiente
¿Debería escribir acerca de este tema en este capitulo ya que aun no hemos hablado de listas y diccionarios?

Algunas veces usted podría querer definir una función que tome cualquier numero de parámetros, esto lo puede lograr usando asteriscos:

#!/usr/bin/python
# Archivo: total.py

def total(inicial=5, *numeros, **palabras_clave):
    cont = inicial
    for numero in numeros:
        cont += numero
    for clave in palabras_clave:
        cont += palabras_clave[clave]
    return cont

print(total(10, 1, 2, 3, vegetales=50, frutas=100))

Salida:

   $ python total.py
   166

Como Funciona:

Cuando declaramos un parámetro con asterisco como *param, todos los argumentos desde ese punto hasta el final son almacenados en una tupla llamada 'param'.

Similarmente, cuando declaramos parámetro con dos asteriscos como **param, todos los argumentos por palabra clave desde ese punto hasta el final son almacenados en un diccionario llamado 'param'.

Exploraremos tuplas y diccionarios en capítulos posteriores.

Parámetros de Solo Palabra Clave

Si queremos especificar cierto parámetro de palabra clave, para que sea solo asequible por palabra clave y no como un argumento posicional, entonces puede ser declarado después de un parámetro con asterisco.

#!/usr/bin/python
# Archivo: keyword_only.py

def total(inicial=5, *numeros, numero_extra):
    cont = inicial
    for numero in numeros:
        cont += numero
    cont += numero_extra
    print(cont)

total(10, 1, 2, 3, numero_extra=50)
total(10, 1, 2, 3)
# Levanta un error porqué no se suministrado un valor por defecto al argumento 'numero_extra'.

Output:

   $ python keyword_only.py
   66
   Traceback (most recent call last):
     File "keyword_only.py", line 12, in <module>
   total(10, 1, 2, 3)
   TypeError: total() needs keyword-only argument extra_number

Como Funciona:

Cuando se declaran parámetros después de un parámetro con asterisco estos se vuelven argumentos de solo palabra clave, si a estos argumentos no se le da un valor por defecto, luego cuando se llama la función y no se le suministra un argumento por palabra clave lanzara un error como se vio anteriormente.

Observe que puede usar += el cual es un operador abreviado, entonces en vez de decir x = x + y, puede decir x += y.

Si quiere tener argumentos de solo palabra clave, pero no tiene la necesidad de un parámetro con asterisco, puede usar simplemente un asterisco sin algún nombre como en def total(inicial = 5, *, numero_extra).

La Instrucción return

La instrucción return es usada para retornar de una función es decir, salir de la función y opcionalmente también podemos retornar un valor de esta.

Ejemplo:

#!/usr/bin/python
# Archivo: func_return.py

def mayor(x, y):
    if x > y:
        return x
    elif x == y:
        return 'Los números son iguales'
    else:
        return y

print(mayor(2, 3))

Salida:

   $ python func_return.py
   3

Como Funciona:

La función mayor retorna el mayor de los parámetros, en este caso los números que se le suministran. Para encontrar el mayor usa una simple instrucción if..else y luego lo retorna.

Tenga presente que una instruccion return sin un valor es equivalente a return None. None es un tipo especial en Python que representa la nada. Por ejemplo si se usa el valor None en una variable, indicaría que esta no tendría un valor.

Todas las funciones implicitamente contienen una instrucción return None al final, a no ser que se halla escrito una instruccion return propia. Por ejemplo esto puede ser visto cuando se corre print(algunaFuncion()) donde la función algunaFuncion no tiene una instrucción return, como esta:

def someFunction():
    pass

La instrucción pass es usada en Python para indicar un bloque vacío de declaraciones.

Nota
Hay una función incluida en Python llamada max que tiene la funcionalidad de hallar el mayor, entonces use esta función incluida en cuanto le sea posible.

Cadenas de Documentación (DocStrings)

Python tiene una excelente característica llamada cadenas de documentación , usualmente se refiere a esta por su nombre corto docstrings, esta es una importare herramienta que debería usar debido a que ayuda a documentar mejor el programa y lo hace fácil de entender. Sorprendentemente, podemos tener acceso el docstring de, por ejemplo una función cuando el programa se encuentra en ejecución.

Ejemplo:

#!/usr/bin/python
# Archivo: func_doc.py

def imprimirMayor(x, y):
    '''Imprime el mayor de dos números.

    Los dos valores deben ser enteros.'''
    x = int(x) # si es posible, los convierte a  enteros
    y = int(y)

    if x > y:
        print(x, 'es el mayor')
    else:
        print(y, 'es el mayor')

imprimirMayor(3, 5)
print(imprimirMayor.__doc__)

Salida:

   $ python func_doc.py
   5 es el mayor
   Imprime el mayor de dos números.
       Los dos valores deben ser enteros.

Como Funciona:

Una cadena de caracteres (string) en la primer linea lógica de una función es el docstring para dicha función. Tenga en cuanta que los DocStrings también aplican para módulos y clases los cuales estudiaremos en sus respectivos capítulos.

La convención seguida para los docstring es: una cadena de varias lineas donde la primer linea empieza con una letra mayúscula y termina con un punto, luego una segunda linea en blanco seguida por cualquier explicación detallada que empieza en la tercer linea. Le recomiendo fuertemente que siga esta convención para todos los docstrings que le haga a todas sus funciones no triviales.

Podemos acceder a la cadena de documentación de la función imprimirMayor usando el atributo __doc__ (observe los guiones bajos) de la función. Recuerde que Python trata todo como un objeto y esto incluye a las funciones. Aprenderemos mas acerca de objetos en el capitulo de clases.

Si has usado help() en Python entonces ya has visto el uso de docstrings!, lo que esta hace es simplemente buscar el atributo __doc__ de una función y imprimirlo de una manera ordenada. Puede intentar esto en la función anterior – solo incluya help(imprimirMayor) a su programa. Recuerde presionar la letra q para salir de help.

Las herramientas automatizadas pueden recuperar la informacion de su programa de esta mantera. Por lo tanto , le recomiendo fuertemente que use docstrings para cualquier función no trivial que escriba. El comando pydoc que viene con su distribución de Python funciona similarmente a help() usando docstrings.

Anotaciones

Las funciones tienen otra avanzada característica llamada anotaciones (annotations), la cual una hábil forma de añadir información adicional para cada uno de los parámetros y también el valor de retorno. Ya que el lenguaje Python por si mismo no interpreta estas anotaciones de ninguna forma (esta funcionalidad es dejada para las librerías de terceros para que interpreten cualquier cosa de la forma que quieran) entonces en nuestra discusión saltaremos esta característica. Si esta interesado en leer acerca de anotaciones, por favor revise Python Enhancement Proposal No. 3107.

Resumen

Hasta ahora hemos visto muchos de los aspectos de las funciones, pero observe que continuamos sin cubrirlos a todos. Sin embargo, ya hemos cubierto mas de lo que usaría en el día a día, con respecto a las funciones en Python.

Ahora, vamos a ver como usar y crear módulos de Python.


Advertisements