In [56]: def test():
....: print('funcion de prueba')
....:
....:
In [57]: test()
funcion de prueba
Advertencia
Después de definir una función deben indentarse los bloques que la componen.
Las funciones pueden opcionalmente devolver valores.
In [6]: def area_circulo(radio):
...: return 3.14 * radio * radio
...:
In [8]: area_circulo(1.5)
Out[8]: 7.0649999999999995
Nota
Por defecto, las funciones devuelven None.
Nota
Tenga en cuenta la sintaxis para definir una función:
Parámetros obligatorios (argumentos con posición)
In [81]: def por_dos(x):
....: return x * 2
....:
In [82]: por_dos(3)
Out[82]: 6
In [83]: por_dos()
---------------------------------------------------------------------------
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: double_it() takes exactly 1 argument (0 given)
Parámetros opcionales (argumentos con nombre o palabra clave)
In [84]: def por_dos(x=2):
....: return x * 2
....:
In [85]: por_dos()
Out[85]: 4
In [86]: por_dos(3)
Out[86]: 6
Los argumentos con nombre le permiten especificar los valores por defecto.
Advertencia
Los valores por defecto se evalúan cuando se define la función, no cuando se le llama. Esto puede ser problemático cuando se utiliza tipos mutables (por ejemplo, un diccionario o una lista) y su modificación en el cuerpo de la función, ya que el modificaciones no persisten al invocar una función.
In [124]: gran_x = 10
In [125]: def por_dos(x=gran_x):
.....: return x * 2
.....:
In [126]: por_dos()
Out[126]: 20
In [127]: gran_x = 1e9 # Ahora si es grande
In [128]: por_dos()
Out[128]: 20
Truco
Un ejemplo que se parece a la segmentación de Python:
In [98]: def segmento(secuencia, inicio=None, final=None, paso=None):
....: """Implementacion basica de segmentacion python."""
....: return secuencia[inicio:final:paso]
....:
In [101]: rima = 'pez uno, pez dos, pez rojo, pez azul'.split()
In [102]: rima
Out[102]: ['pez', 'uno,', 'pez', 'dos,', 'pez', 'rojo,', 'pez', 'azul']
In [103]: segmento(rima)
Out[103]: ['pez', 'uno,', 'pez', 'dos,', 'pez', 'rojo,', 'pez', 'azul']
In [104]: segmento(rima, paso=2)
Out[104]: ['pez', 'pez', 'pez', 'pez']
In [105]: segmento(rima, 1, paso=2)
Out[105]: ['uno,', 'dos,', 'rojo,', 'azul']
In [106]: segmento(rima, inicio=1, final=4, paso=2)
Out[106]: ['uno,', 'dos,']
El orden de los argumentos con nombre no importa:
In [107]: segmento(rima, paso=2, inicio=1, final=4)
Out[107]: ['uno,', 'dos,']
pero es una buena práctica usar el mismo orden que en la definición.
Los argumentos con nombre son una característica muy conveniente para la definición de funciones con un número variable de argumentos, sobre todo cuando los valores por defecto se usan en la mayoría de las llamadas a la función.
Truco
Se puede modificar el valor de una variable dentro una función? La mayoría de los lenguajes (C, Java, ...) distinguen el paso por valor y el paso por referencia. En Python, tal distinción es un tanto artificial, y es un poco sutil si las variables serán modificadas o no. Afortunadamente, existen reglas claras.
Los parámetros a funciones son referencias a los objetos, que se pasan por valor. Cuando se pasa una variable a una función, Python pasa la referencia al objeto al que hace referencia la variable (el valor). No es la propia variable.
Si el valor pasado a una función es inmutable, la función no modifica la variable llamada. Si el valor es mutable, la función puede modificar la variable
>>> def intenta_modificar(x, y, z):
... x = 23
... y.append(42)
... z = [99] # nueva referencia
... print x
... print y
... print z
...
>>> a = 77 # variable immutable
>>> b = [99] # variable mutable
>>> c = [28]
>>> intenta_modificar(a, b, c)
23
[99, 42]
[99]
>>> print a
77
>>> print b
[99, 42]
>>> print c
[28]
Las funciones tienen una tabla de variables locales llamada local namespace.
La variable x sólo existe dentro la función intenta_modificar.
Las variables declaradas fuera de una función pueden referenciarse a una función:
In [114]: x = 5
In [115]: def suma_x(y):
.....: return x + y
.....:
In [116]: suma_x(10)
Out[116]: 15
Pero estas variables globales no se pueden modificar dentro de la función, a menos que se declare como global en la función.
Esto no funciona:
In [117]: def asigna_x(y):
.....: x = y
.....: print 'x is %d' % x
.....:
.....:
In [118]: asigna_x(10)
x is 10
In [120]: x
Out[120]: 5
Esto si funciona:
In [121]: def asigna_x(y):
.....: global x
.....: x = y
.....: print 'x is %d' % x
.....:
.....:
In [122]: asigna_x(10)
x is 10
In [123]: x
Out[123]: 10
Formas especiales de los parámetros:
In [35]: def argumentos_variables(*args, **kwargs):
....: print 'args es', args
....: print 'kwargs es', kwargs
....:
In [36]: argumentos_variables('uno', 'dos', x=1, y=2, z=3)
args es ('uno', 'dos')
kwargs es {'y': 2, 'x': 1, 'z': 3}
Documentación sobre lo que hace la función y sus parámetros. Convención general:
In [67]: def funcion_ejemplo(parametros):
....: """Frase concisa de una línea que describe la funcion.
....:
....: Resumen extendido que puede contener varios parrafos.
....: """
....: # cuerpo de funcion
....: pass
....:
In [68]: funcion_ejemplo?
Type: function
String Form:<function funcion_ejemplo at 0x9893e9c>
File: /home/claudio/<ipython-input-4-3c894f027eb2>
Definition: funcion_ejemplo(parametros)
Docstring:
Frase concisa de una línea que describe la funcion.
Resumen extendido que puede contener varios parrafos.
Nota
Guia para docstrings
Para estandarizar la documentación, revise la página web Docstring Conventions contiene documentos de semántica y convenios relacionados con Python docstrings.
Además, los módulos numpy y scipy han definido un estándar preciso para la documentación de las funciones científicas, es posible que desee seguir para sus propias funciones, con una sección Parámetros , una sección Ejemplos, etc. Ver http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines#docstring-standard y http://projects.scipy.org/numpy/browser/trunk/doc/example.py#L37
Las funciones son la primera clase de objetos, lo que significa que puede:
In [38]: va = argumentos_variables
In [39]: va('tres', x=1, y=2)
args es ('tres',)
kwargs es {'y': 2, 'x': 1}
Los métodos son funciones vinculadas a los objetos. Usted ha visto esto en los ejemplos de listas, diccionarios, cadenas, etc ..
Ejercicio: Serie de Fibonacci
Escriba una función que muestre los n primeros términos de la serie de Fibonacci, definido por:
- u_0 = 1; u_1 = 1
- u_(n+2) = u_(n+1) + u_n
Ejercicio: Quicksort
Implemente el algoritmo quicksort, definido por wikipedia:
var list less, greater if length(array) < 2
return array
select and remove a pivot value pivot from array for each x in array
if x < pivot + 1 then append x to less else append x to greater
return concatenate(quicksort(less), pivot, quicksort(greater))