Funciones en python

Las funciones en Python como en otros lenguajes, son muy útiles para separar bloques de código que necesitamos en distintos lugares de un programa. Las funciones en Python se diferencian de las funciones en C/C++ en que éstas siempre devuelven un valor (por tanto no hay cabida a la definición de procedimientos). Si una función en Python no retorna un valor con la palabra reservada return, ésta devolverá “None”.

Definición de una Función:

Para definir una función en Python se usa la palabra reservada “def” seguida del nombre de la función y entre paréntesis los parámetros separados por comas. Dentro de nuestra definición de función debe ir el bloque de código que ejecutará nuestra función.

>>> 
>>> def m(a, b):
... print a
... print b
... 
>>>


Invocando Una Función:

Para llamar a nuestra función solo requerimos indicar el nombre de nuestra función (para nuestro ejemplo nuestra función se llama “m”), e indicarle los parámetros que tenga definidos.

>>> a = m('si ', 1)
si 
1
>>>

Como se mencionó antes, las funciones en Python a diferencias de los procedimientos en otros lenguajes retornan un valor None.

>>> if m('si ', 1) is None:
... print "La funcion retorna None"
... 
si 
1
La funcion retorna None
>>>

Las funciones en Python crean una “Tabla de Simbolos Local“, por lo que la referencia a una variable primero mira la Tabla Local, luego la “Tabla de Simbolos Global” y por último en la “Tabla de Simbolos Interna“. Por esto dentro de una función no se le puede asignar un valor a una variable global (A memos que ésta esté declarada por una sentencia global).

>>> 
>>> global a
>>> a = 3
>>> 
>>> def imp():
... print a
... 
>>> imp()
3
>>>
>>> global x 
>>> x = 2
>>> 
>>> def i():
... global x
... x += 1
... 
>>> i()
>>> x
3
>>> 
>>> global z 
>>> z = 2
>>> 
>>> def j():
... z = z + 3
... 
>>> j()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "<stdin>", line 2, in j
UnboundLocalError: local variable 'z' referenced before assignment
>>>

Una definición de función introduce el nombre de la función en la “Tabla de Simbolos” vigente. Ese nombre de función tiene un tipo reconocido por el intérprete y se puede asignar a otro nombre y usar éste, ya que adquiere todas las características del tipo función.

>>> imp
<function imp at 0xb74489cc>
>>> 
>>> a = imp
>>> a
<function imp at 0xb74489cc>
>>> 
>>> type(imp)
<type 'function'>
>>> type(imp())
3
<type 'NoneType'>
>>> print imp()
3
None
>>>

La sentencia Return:

Es usada para devolver la ejecución al que llamó a la función, devolviendo un valor o sin argumentos para salir de la función (si el bloque de código dentro de la función se acaba, también nos salimos de la función, con un valor de retorno “None”). Creemos una función que nos devuelva la potencia de un número.

>>> 
>>> def potencia(base, exp):
... return base**exp
... 
>>> p = potencia(2, 3)
>>> p
8
>>>

En Python existen tres formas de definir funciones con un número variable de argumentos, las cuales se pueden combinar. Estas son:

Valores por Omisión.
Argumentos por Clave.
Listas de Argumentos Arbitrarias.

Valores Por Omisión:

Este tipo de definición crea una función la cual se puede llamar con menos argumentos de los que tiene definidos y es la forma más útil de especificar un valor por omisión para uno o más argumentos.

>>> def potenciaCuadrado(n, p=2):
... """Función que realiza un cuadrado cuando ingresan dos
... argumentos o un cuadrado cuando ingresas un argumento"""
... return n**p
... 
>>> potenciaCuadrado(3)
9
>>> potenciaCuadrado(3, 4)
81
>>> potenciaCuadrado(2, 4)
16
>>> potenciaCuadrado(3, 2)
9
>>> potenciaCuadrado(5)
25
>>> potenciaCuadrado(3)
9
>>> potenciaCuadrado()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: potenciaCuadrado() takes at least 1 argument (0 given)
>>>

Si llamamos a la función “potenciaCuadrado” con un solo argumento se le asignará a “p” su valor por omisión “2“. Y si llamamos a “potenciaCuadrado” con dos argumentos estos se asignarán de izquierda a derecha. Los valores por omisión se evaluan en el instante de la definición de la función, así:

>>> 
>>> p = 3
>>> def f(a=p):
... print a
... 
>>> p = 4
>>> f()
3
>>>

Hay que tener en cuenta que el argumento por omisión se evalúa una sola vez. Lo cual lleva a diferentes resultados cuando el valor por omisión es un “objeto mutable“, como una lista o un diccionario. Por ejemplo podemos acumular las llamadas sucesivas a nuestra función “potenciaCuadrado“.

>>> def potenciaCuadrado(n, p=2, l=[]):
... l.append("%s**%s" % (n,p))
... print l
... return n**p
... 
>>> potenciaCuadrado(3)
['3**2']
9
>>> potenciaCuadrado(5)
['3**2', '5**2']
25
>>> potenciaCuadrado(5, 8)
['3**2', '5**2', '5**8']
390625
>>> potenciaCuadrado(1, 4)
['3**2', '5**2', '5**8', '1**4']
1
>>>

Si no deseamos que el valor por omisión sea compartido por sucesivas llamadas, podemos especificar un valor por omisión None para el objeto mutable, y ya que cada vez que se ingresa al bloque de una función esta cuenta con su Tabla Simbolica Local nueva, no se guardaría dicho objeto mutable.

>>> 
>>> def potenciaCuadrado(n, p=2, l=None):
... if l is None:
... l = []
... l.append("%s**%s" % (n, p))
... print l
... return n**p
... 
>>> potenciaCuadrado(3, 5)
['3**5']
243
>>> potenciaCuadrado(2, 3)
['2**3']
8
>>> potenciaCuadrado(7)
['7**2']
49
>>> potenciaCuadrado(3, 3, [])
['3**3']
27
>>>

Argumentos por Clave:

También podemos llamar a una función utilizando la forma ‘clave=valor‘ asemejándonos a un diccionario. Si usamos nuestro ejemplo anterior veremos cómo se invocan los argumento por clave:

>>> potenciaCuadrado(p=2, n=3)
['3**2']
9
>>> potenciaCuadrado(p=2, n=3, l=[])
['3**2']
9
>>> potenciaCuadrado(l=[], n=2)
['2**2']
4
>>>

Donde la “clave” es el nombre con que se creó el parámetro en el momento de definir la función y el “valor“, serían los datos asignados al parámetro. En nuestro ejemplo el parámetro “n“, corresponde a un argumento posicional ya que este solo puede ser referenciado como el primer argumento a no ser que sea invocado como una “clave”. Mientras tanto los parámetros “p” y “l“, funcionan como “argumentos por clave“.

En general, una lista de argumentos debe tener “argumentos posicionales” seguidos por “argumentos clave“. Pero hay que tener en cuenta que los nombres de parámetros formales correspondientes a argumentos posicionales no se pueden usar como claves en la misma llamada. P.e:

>>> potenciaCuadrado(2, n=3)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: potenciaCuadrado() got multiple values for keyword argument 'n'
>>>
>>> def a(i=8, f):
... pass
... 
 File "<stdin>", line 1
SyntaxError: non-default argument follows default argument
>>>

Ya habíamos comentado que los Argumentos por Clave se asemejan a un diccionario; por esto cuando el último parámetro formal de la declaración de la función tiene la forma **argumento recibe un diccionario que contiene todos los argumentos clave, cuya clave no corresponde con ningún parámetro formal. (El funcionamiento de esta característica la veremos en la próxima sesión).

Listas de Argumentos Arbitrarias:

Las funciones de argumentos arbitrarios, nos permiten llamar a nuestra función con un número arbitrarios de argumentos, los cuales se agrupan en una tupla y se indica con la forma *argumento. Antes del número variable de argumentos pueden haber cero o más argumentos normales. Este tipo de funciones son útiles en el momento que requiramos de una función que nos permita en el momento de llamarla, excedernos en la lista de parámetros formales.

>>>
>>> def g(*listarg):
... print listarg
... 
>>> g(1,2,3,4)
(1, 2, 3, 4)
>>>
>>> def c(*listarg):
... a = 0
... for i in listarg:
... a += i
... return a
... 
>>> c(1,2,3,4)
10
>>>

Python solo soporta el uso del diccionario “clave=valor” **arg (descrito en la sesión anterior) si esta precedido por la “tupla de argumentos arbitrarios” *arg.

>>>
>>> def cliente(nombre, *ids, **contactos):
... print nombre,
... for id in ids: print id 
... print "-"*50
... for k, v in contactos.items():
... print "%s : %s" % (k.ljust(15), v)
... 
>>> cliente('Jolth', "112339008", "6772347234", celular=3545778656, pbx=5703442233, fax=77823499)
Jolth 112339008
6772347234
--------------------------------------------------
fax : 77823499
celular : 3545778656
pbx : 5703442233
>>>

Como conclusión podemos decir que la lista de argumentos arbitrarios (*arg), nos sirven para definir una lista de “argumentos por omisión” y que para definir una cantidad arbitraria de “argumentos por clave” se debe usar un diccionario de argumentos clave=valor (**arg).

Autor: Jolth

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s