Funciones
Existe una distinción teórica que me gusta remarcar acerca de las funciones que, si bien al momento de crear una no es relevante, considero importante hacer. Hay un tipo de función que puede categorizarse junto con los condicionales y los bucles: esto es, sirve para agrupar un conjunto de instrucciones bajo un mismo nombre para evitar repetirlas a lo largo del código. El otro, es el concepto de función tal como se conoce en matemática: una función obtiene un valor o un conjunto de valores de entrada, aplica una serie de operaciones y retorna un valor o un conjunto de valores de salida, un resultado.
Como sea, empecemos por un ejemplo simple. Definamos una función
dup(n)
, muy al estilo matemático, que tome como argumento un número
y retorne el doble.
def dup(n):
return n * 2
Introdujimos dos palabras reservadas nuevas. def
es empleada siempre
que se quiera crear una nueva función, seguida de su nombre
(que, al igual que las variables, se escribe en minúscula y separada
por guiones bajos) y los argumentos entre paréntesis y separados por
comas. return
debe estar sucedida por una expresión que será el
valor de retorno de la función. Iremos aclarando estos conceptos.
Por el momento, hagamos una prueba:
# Imprime 10 en pantalla.
print(dup(5))
Ahora consideremos esta otra definición.
def saludar(nombre):
print("Hola", nombre)
saludar("mundo")
En este caso, nuestra función saludar()
no retorna ningún valor.
Aunque, en efecto, Python le asigna un valor de retorno por defecto
llamado None
. Se trata de un tipo de dato como los que hemos estado
trabajando, pero un tanto más particular, ya que intenta indicar que
una variable está vacía.
>>> a = None
>>> b = 3.14
>>> a is None
True
>>> b is not None
True
La única diferencia, como se observa, es que para realizar
comparaciones respecto de None
utilizamos las palabras reservadas
is
e is not
en lugar de ==
y !=
.
Argumentos
En Python los argumentos de las funciones tienen un comportamiento particular a diferencia de otros lenguajes. Tomemos como ejemplo la siguiente función.
def sumar(a, b):
return a + b
De ella decimos que tiene dos argumentos posicionales. Llevan ese
nombre por cuanto al invocar sumar(7, 5)
, 7
se corresponde con a
por ser el primer argumento, y 5
se corresponde con b
por ser el
segundo. Si lo invertimos, de modo que llamemos a sumar(5, 7)
,
entonces ahora a == 5
y b == 7
.
Además, al invocar a una función con argumentos posicionales, estos siempren deben tener un valor. Por ejemplo, las siguientes llamadas arrojan un error.
# Falta especificar el argumento b.
sumar(7)
# Sobra un argumento.
sumar(7, 5, 3)
Ahora bien, una función puede tener argumentos con valores por defecto, de modo que, al llamarla, si no hemos especificado un valor concreto por argumento, éste toma automáticamente el que la definición le ha asignado por defecto.
def sumar(a, b=5):
return a + b
# ¡Perfecto! Imprime 12.
print(sumar(7))
# En este caso, b == 10.
print(sumar(5, 10))
Agreguemos, para avanzar un poco más, un tercer argumento c
con un
valor por defecto.
def sumar(a, b=5, c=10):
return a + b + c
# Imprime 22 (7 + 5 + 10).
print(sumar(7))
¿Qué ocurre si quiero indicar un valor para el argumento c
mientras
que b
mantenga su valor por defecto? En ese caso, en lugar de pasar
el argumento por posición, lo voy a pasar por nombre.
# Imprime 32 (7 + 5 + 20).
print(sumar(7, c=20))
La posibilidad de pasar argumentos por su nombre en la llamada a una función solo puede darse en aquellos que tengan un valor por defecto. De ahí que a estos se los conozca como argumentos por nombre. En estos casos, la posición de los argumentos es indistinta, de modo que el siguiente código es perfectamente válido.
# El orden es indistinto en los argumentos por nombre.
print(sumar(7, c=20, b=10))
(Nótese que, por convención, cuando especificamos el valor de un argumento por nombre no se ubican espacios alrededor del signo igual).
La única restricción es que los argumentos posicionales deben preceder a los argumentos por nombre, tanto en la definición de una función como en la llamada. El siguiente ejemplo no es un código válido de Python.
# ¡¡¡Inválido!!!
def sumar(a=5, b):
return a + b
Python provee otras herramientas interesantes para trabajar con los argumentos. Por ejemplo, la posibilidad de crear funciones con argumentos infinitos. Véase, para ahondar en ellas, el siguiente artículo: Argumentos en funciones.
Documentación
Cuando diseñamos una función, lo ideal es documentar su comportamiento utilizando comillas triples inmediatamente luego de su definición.
def dup(n):
"""
Retorna el doble de `n`.
"""
return n * 2
Cuando la documentación es más bien corta, como la que hemos mostrado, podemos ubicarla por completo en la misma línea, incluso usando comillas simples.
def dup(n):
"Retorna el doble de `n`."
return n * 2
Si bien en la documentación de una función podemos escribir lo que se
nos antoje, ¡no es lo mismo que un comentario! En realidad, como
habrás observado, es una cadena de Python, que luego el intérprete le
asignará como un atributo a la función. Para conocer el docstring
(este es el término correcto) de una función podemos emplear la
función incorporada help()
.
# Imprime la documentación en pantalla.
help(dup)
Esta función es especialmente útil en la consola, dado que te permite conocer el funcionamiento y la estructura de argumentos de todas las funciones incorporadas.
>>> help(print)
[...]
>>> help(int)
[...]
Perfecto, ya tenemos todo lo necesario para introducirnos en las clases. Si te parece, ¡sigamos!