Funciones definidas por el usuario

Definición de función y su utilidad

Una función en informática se refiere al conjunto de instrucciones y expresiones que realizan una tarea en particular aparte del programa desde donde son invocadas, incluso desde otros programas. Además las funciones también pueden responder a eventos, aceptar datos como parámetros y pueden eventualmente devolver datos de igual manera. Es importante destacar que las funciones solo se ejecutan en el momento en que son llamadas, cual permite reutilizar el mismo código de manera indefinida tantas veces como sea necesario. Otra gran ventaja que permite el uso de funciones es la posibilidad de dividir el programa en partes mas pequeñas creando segmentos de código para que trabajen en armonía unos con otros. En Python ya existen algunas funciones propias del lenguaje que están incorporadas en la biblioteca estándar. Sin embargo Python al igual que otros lenguajes de programación, no está limitado al uso exclusivo de las funciones incorporadas en su biblioteca.

Es importante mencionar que las funciones y métodos son sinónimos siempre y cuando la función este dentro de una clase. Esto se ve mas a detalle en el apartado de POO

Funciones definidas por el usuario

En Python es posible definir funciones adicionales personalizadas, también llamadas funciones definidas por el usuario. Para definir una función personalizada se usa la palabra reservada DEF, seguido del nombre de la función y entre paréntesis () los parámetros a recibir opcionalmente separados por coma y dos puntos (:). Es importante en la primera línea de la función dejar una indentación o sangrado para que Python reconozca el cuerpo de la función y el final de la misma. Entonces la sintaxis para definir una función personalizada es como sigue:

DEF <nombre de la función>  (<parámetros opcionales>):

    <instrucciones propias de la función>

    return <valor opcional>

La instrucción RETURN es opcional, ya que como se dijo anteriormente, la devolución de valores en una función es opcional, por lo tanto si la función devuelve valores se usará RETURN seguido de los valores devueltos, y si no devuelve VALORES simplemente se omite.

Las reglas para definir el nombre de la función son las mismas que las que se vieron previamente para definir los nombres de las variables

Como podemos ver el paso de argumentos a las funciones al igual que la devolución de valores son opcionales. Sin embargo obligatorio en la definición de funciones el uso de la palabra reservada DEF antepuesta al nombre o identificador de la función y el uso de los 2 puntos (:) con las correspondientes instrucciones debidamente sangradas que componen el cuerpo de la función. También es obligatorio enviar los argumentos a la función con el tipo y la cantidad definida en caso de haber definido parámetros de entrada a la función, en caso contrario el intérprete devolverá un error- Veamos un ejemplo de este caso:

def suma(a,b):
    return a+b

print(suma())

Resultado:

Traceback (most recent call last):

  File "e:\Documentos\Desarrollos\Python\Curso-Python\10 Funciones definidas por el usuario.py", line 350, in <module>

    print(suma())

TypeError: suma() missing 2 required positional arguments: 'a' and 'b'

Como podemos ver el error esta relacionado a que se requieren 2 argumentos que no están siendo enviados a la función como se esperaba. Veamos la solución a este problema:

def suma(a,b):
    return a+b

print(suma(3,2))

Resultado:

5

Como podemos comprobar la función esta funcionando como se esperaba y sin errores.

Una vez definida la función basta con escribir el identificador o nombre de la función (y sus parámetros en caso que los tenga) para ejecutarla, tal cual como si fuera cualquier otra instrucción en Python de las que hemos visto previamente. Si no es invocada a función nunca va a ejecutarse. Hay que tomar en cuenta que se deben colocar los paréntesis al llamara una función aunque no se vayan a pasar parámetros. Veamos el siguiente ejemplo:

def holaMundo():
    print('Hola mundo')

holaMundo()

Resultado:

Hola mundo

Durante el desarrollo de un sistema es muy común que se presente la necesidad de crear funciones personalizadas que realicen una tarea en particular pero que se haga necesario postergar su codificación para después y seguir con el flujo del programa principal. Sin embargo Python no permite la creación de funciones vacías o sin al  menos una línea de código dentro de ellas. Es por ello que existe la instrucción PASS, su sintaxis es simplemente la palabra reservada 'pass'. Veamos el siguiente ejemplo:

def FuncionVacia():

print('Se ejecuta el código sin problemas')

Resultado:

IndentationError: expected an indented block after function definition on line 104

El intérprete de Python erroja un error al no encontrar ninguna instrucción con el debido sangrado indicando el inicio del bloque de instrucciones de la función FuncionVacia(). De hecho sugiere que puede ser un error de sangrado al encontrar una instrucción al mismo nivel que la definición de la función. Sin embargo, si deseamos poder seguir trabajando en el programa principal pero dejando la función creada basta con usar la palabra reservada 'pass'. Veamos el siguiente ejemplo:

def FuncionVacia():
    pass

print('Se ejecuta el código sin problemas')

Resultado:

Se ejecuta el código sin problemas

Como podemos ver se ha ejecutado el código del programa principal, teniendo una función declarada sin instrucciones en su bloque de código salvo la que devuelve el flujo de la ejecución del programa al bloque principal donde se creó dicha función.


En el ejemplo anterior se puede observar el uso básico de funciones, veamos como sería el uso de parámetros en una función definida por el usuario en el siguiente ejemplo:

def saludar(sNombre):
    print(f'Hola {sNombre}')

sNombre = input('Ingrese su nombre:')
saludar(sNombre)

Resultado ingresando la cadena 'Cesar' por teclado cuando el programa lo solicita:

Ingrese su nombre:Cesar

Hola Cesar

Como podemos comprobar la función identificada con el nombre <saludar> ha aceptado como parámetro la cadena de caracteres ingresada por teclado a través de la variable sNombre, para posteriormente imprimirlo por pantalla a través de la función incorporada PRINT(). Una vez invocada la función definida pasando el parámetro 'Cesar', ésta ejecuta las instrucciones que se encuentren luego de los 2 puntos (:) y que esten dento del sangrado de la  misma función.

Es muy importante mantener el sangrado de las instrucciones a fin de evitar errores en la definición de las funciones, tales como instrucciones que quedan fuera de la función o la inclusión errada de instrucciones externas, hay que recordar que Python va a entender que todas las instrucciones que encuentre a continuación de los dos puntos (:) forman parte del conjunto de instrucciones que componen la función, determinando el final del bloque de código al encontrar el sangrado restablecido antes de la declaración de la función.

En este apartado se ha hecho uso de la función incorporada en Python llamada INPUT(). PAra mas detalles de ésta función ver el apartado funciones incorporadas en Python.

Veamos otro ejemplo con retorno de valores:

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

iValorA = int(input('Ingrese el primer valor a sumar:'))
iValorB = int(input('Ingrese el segundo valor a sumar:'))

print(f'La suma de {iValorA} + {iValorB} da como resultado {sumar(iValorA,iValorB)}')

Resultado ingresando los valores 3 y 2 por teclado cuando el programa solicita el ingreso de datos:


Ingrese el primer valor a sumar:3

Ingrese el segundo valor a sumar:2

La suma de 3 + 2 da como resultado 5

Como se puede observar, la función definida por el usuario con el nombre <sumar> ha aceptado 2 valores enteros definidos como parámetros de entrada en las variables x e y, luego ha almacenado el resultado de la operación suma en la variable identificada con el nombre 'resultado' y ha retornado dicho valor a través de dicha variable luego de la palabra reservada return. En el programa principal, desde donde se ha invocado la función <sumar>, se ha impreso por pantalla un mensaje que muestra la operación realizada, los valores ingresados por el usuario para realizar la operación y el resultado de dicha operación a través de la invocación de la función sumar() pasando como argumentos los 2 valores solicitados por teclado almacenados en las variables iValorA e iValorB.

Nota: existe una diferencia importante entre las palabras 'parámetro' y 'argumento' en lo que se refiere al uso de funciones en informática. Los parámetros son los elementos declarados en el prototipo de las funciones que admiten valores para ser procesados dentro de la función, mientras que los argumentos son los datos como tal que se son enviados a la función. En el ejemplo anterior, los parámetros serían x e y, ya que son los medios para recibir los datos a ser procesados, mientras que los argumentos serian iValorA e iValorb, ya que contienen efectivamente la data a ser procesada. De igual forma es importante destacar que los argumentos en tiempo de diseño se llaman argumentos formales y en tiempo de ejecución se llaman argumentos actuales. En el ejemplo anterior, y siguiendo la nomenclatura mencionada los argumentos actuales serian los números 3 y 2, correspondientes a los argumentos formales iValora e iValorB que van a ser recibidos por la función definida por el usuario SUMAR() a través de los parámetros x e y.

Paso de argumentos por valor y por referencia

Un punto importante para aclarar en informática es el paso de valores a las funciones ya que existen 2 tipos bien definidos, paso de argumentos por valor y paso de argumentos por referencia. El paso de argumentos por valor es el comportamiento de la función mediante el cual se crea una copia local de la variable pasada como argumento con lo cual las variables originals no se verán afectadas, es decir se le indica a la función el valor de los parametros mas no el identificador externo que los contiene. Mientras que el paso de argumentos por referencia es el comportamiento mediante el cual la función maneja directamente el espacio de memoria de las variables recibidas, con lo cual cualquier modificación dentro de la función afectará a las variables externas involucradas, es decir la función recibe la referencia o ubicación de memoria del identificador de la variable y trabajara sobre ese contenido directamente. En resumen: Paso de argumento por valor = no modifica las variables externas de la función. Paso de argumentos por referencia = modifica las variables externas de la función.

Veamos el siguiente ejemplo:

def modifica_referencia(a,b):
    a+=1
    b+=1
    return a,b
print(modifica_referencia(10,20))

Resultado:

(11, 21)

Como podemos comprobar Python ha modificado las variables externas a y b sumando una unidad como se especificó dentro de la función modifica_referencia.

Sentencia RETURN

Como se vió anteriormente, la sentencia RETURN es opcional y solamente se ha usado hasta ahora para devolver un dato al finalizar la función. Sin embargo puede haber mas de una sentencia RETURN dentro de una función, haciendo que se salga de la función en cualquier parte del bloque de código que la compone, siendo la siguiente instrucción que ejecutará el intérprete de Python la que encuentre en la línea de código que esté inmediatamente a continuación de la llamada a la función.

Veamos el siguiente ejemplo:

def FuncionRango(iNumero):
    if iNumero > 0 and iNumero <=10:
        sRango = 'Rango seleccionado: A (entre 1 y 10)'
        print('Esta línea de código SI se va a ejecutar')
        return sRango
        print('Esta linea de código NO se va a ejecutar')
    elif iNumero >10 and iNumero <=20:
        sRango='Rango seleccionado: B (entre 11 y 20)'
        print('Esta línea de código SI se va a ejecutar')
        return sRango
        print('Esta linea de código NO se va a ejecutar')
    elif iNumero >21 and iNumero <=30:
        sRango='Rango seleccionado: C (entre 21 y 30)'
        print('Esta línea de código SI se va a ejecutar')
        return sRango
        print('Esta linea de código NO se va a ejecutar')
    else:
        print('Esta línea de código SI se va a ejecutar')
        sRango='*** Error Numero introducido invalido (entre 1 y 30) ***'
        return sRango
        print('Esta línea de código NO se va a ejecutar')

iNumero = int(input('Ingrese un número entre 1 y 30: '))

print(FuncionRango(iNumero))

Resultado ingresando 7:

Ingrese un número entre 1 y 30: 7
Esta línea de código SI se va a ejecutar
Rango seleccionado: A (entre 1 y 10)

Resultado ingresando 14:

Ingrese un número entre 1 y 30: 14
Esta línea de código SI se va a ejecutar
Rango seleccionado: B (entre 11 y 20)

Resultado ingresando 25:

Ingrese un número entre 1 y 30: 25
Esta línea de código SI se va a ejecutar
Rango seleccionado: C (entre 21 y 30)

Resultado ingresando 33:

Ingrese un número entre 1 y 30: 33
Esta línea de código SI se va a ejecutar
*** Error Numero introducido invalido (entre 1 y 30) ***

Como podemos ver las instrucciones que están dentro del bloque de código que corresponde con el rango seleccionado y luego del comando RETURN, no se ejecutan, sin embargo si se ejecutan las que estan dento del bloque y son previas al comando RETURN.

Retorno de varios valores en una misma instrucción RETURN

En Python es posible devolver varios valores con una única sentencia RETURN, a través de una TUPLA compuesta con los valores resultantes de la función. Veamos el siguiente ejemplo:

def sumaymultiplicacion(x,y):
    return (x+y),(x*y)

a=int(input('Ingrese el primer valor a sumar y multiplicar: '))
b=int(input('Ingrese el segundo valor a sumar y multiplicar: '))

iSuma,iMultiplicacion = sumaymultiplicacion(a,b)
print(type(sumaymultiplicacion(a,b)))
print(f'{a} y {b} sumados da: {iSuma}, mientras que multiplicados da: {iMultiplicacion}')

Resultado:

Ingrese el primer valor a sumar y multiplicar: 3
Ingrese el segundo valor a sumar y multiplicar: 4
<class 'tuple'>
3 y 4 sumados da: 7, mientras que multiplicados da: 12

Como podemos ver la función definida por el usuario sumaymultiplicacion() ha recibido 2 argumentos a través de sus parámetros x e y y ha devuelto un objeto tipo tupla que contiene 2 valores con una única instrucción RETURN, que era lo que se quería ilustrar con el ejemplo. Al pasarle a la función TYPE() la función sumaymultiplicacion(a,b), el objeto que es devuelto es identificado como del tipo tupla, y imprimir por pantalla los valores de los objetos iSuma e iMultiplicación, que son recogidos llamando a la función sumaymultiplicacion() con los 2 valores ingresados por el usuario, el resultado es la suma y la multiplicación de ambos valores respectivamente, lo que era la razón de ser de la función definida.

Para finalizar el tema de la instrucción RETURN, hay que decir que en Python todas las funciones  definidas por el usuario siempre devuelven un valor. En caso que no se especifique ningún valor tras la instrucción RETURN, o no se haya colocado dicha instrucción, Python por defecto devuelve NONE. Veamos el siguiente ejemplo:

def Prueba():
    print('Esta función no devuelve ningún valor con RETURN')

print(Prueba())

Resultado:

Esta función no devuelve ningún valor con RETURN
None

Como podemos comprobar, Python ejecuta la función aún sin una instrucción RETURN, pero siempre devuelve un valor, en este caso devuelve NONE.

Parámetros por posición

Un punto importante al hablar de parámetros en las funciones en Python es la posición en que se reciben los argumentos. Normalmente el primer argumento es procesado en el primer parámetro de la función, el segundo argumento en el segundo parámetro y así sucesivamente. Sin embargo es posible que este orden no siempre sea el mas conveniente. Veamos el siguiente ejemplo:

import os
os.system('cls')

def resta(a,b):
    iResultado=a-b
    return iResultado

print(f'La resta de 20 y 10 es: {resta(10,20)}')

Resultado:

La resta de 20 y 10 es: -10

Como podemos ver Python ha restado los valores enviados en la misma posición en que fueron pasados los argumentos, dando un resultado negativo ya que 10-20=-10. Sin embargo es posible alterar a posición en la que la función asigna los argumentos a los parámetros en las funciones. Para esto basta con asignar en la misma invocación de la función los valores a los parámetros. Ejemplo:

import os
os.system('cls')

def resta(a,b):
    iResultado=a-b
    return iResultado

print(f'La resta de 20 y 10 es: {resta(b=10,a=20)}')

La resta de 20 y 10 es: 10

Como podemos comprobar ahora el resultado es 10 positivo por que efectivamente se ha cambiado el orden en que la función recibe los argumentos y los asigna a los parámetros, enviando los datos por nombre y no por posición.

Entradas por scripts

Así como es posible pasar argumentos a las funciones definidas por el usuario, también es posible pasar argumentos a los propios scripts del programa o archivos .py que lo conforman. Para que un script de Python pueda recibir argumentos es necesario acceder al módulo SYS. Para ello basta con usar el comando import seguido del nombre del módulo sys. Este módulo otorga acceso a variables y funciones que interactúan con el intérprete de Python. Veamos el siguiente ejemplo:

import os
import sys


def main():
   
    if len(sys.argv) == 3:
        os.system('cls')
        texto = sys.argv[1]
        cantidad = int(sys.argv[2])
        for _ in range(0,cantidad):
            print(texto)
    else:
        print('Error: entrada de argumentos inválida')
        print('Ejemplo: entrada-script.py "Texto" 5')
   

if __name__ == '__main__':
    main()


Resultado:

E:\Documentos\Desarrollos\Python\Curso-Python>"C:/Program Files/Python310/python.exe" e:/Documentos/Desarrollos/Python/Curso-Python/entrada-script.py "Prueba" 2
Prueba
Prueba

Lo que ha sucedido es que para empezar al importar el módulo sys ahora tenemos acceso a algunas variables interesantes del intérprete de Python. Por ejemplo a variable argv, la cual se llama a través del comando sys.argv, y retorna una lista con todos los argumentos recibidos a través de la línea de comandos. Hay que recordar que para poder pasar argumentos a un script es necesario hacerlo desde la consola de comandos, en nuestro caso hemos escrito: entrada-script.py "Prueba" 2 antecedido de la ruta de archivo .py.

Se ha definido una función principal llamada main(), la cual para empezar verifica la cantidad de argumentos recibidos por línea de comandos, en este caso en particular constata que se hayan recibido 3 parámetros exactamente usando la variable argv del objeto sys. En caso de que coincida la cantidad de argumentos recibidos con el número 3, asigna el contenido del elemento 2 de la lista a una variable llamada texto y el contenido del elemento 3 a una variable llamada cantidad. A continuación se inicia un bucle FOR en un rango creado desde 0 hasta el valor almacenado en la variable cantidad e cual solamente va a imprimir por pantalla el contenido de la variable texto. Dando como resultado la impresión por pantalla del texto pasado como argumento por la línea de comandos la cantidad de veces escrita en el último parámetro. Nótese en el bucle FOR el uso del caracter underscore (_). donde se ha sustituido en lugar del uso de una variable entera arbitraria. Aunque mas adelante se verá mas a fondo las diferentes funcionalidades del símbolo underscore (_) en Python, de momento es útil saber que se puede usar el símbolo _ como si una variable se tratara en bucles de repetición. En nuestro caso equivaldría a haber escrito "x" o cualquier otra letra para usar como identificador de una variable.






Comentarios

Entradas populares