Funciones#


DEFINICIÓN#

Función. Una función en Python es una pieza de código reutilizable que solo se ejecuta cuando es llamada. Se define usando la palabra reservada def y su estructura general es la siguiente:

def nombre_funcion(input1, input2, ..., inputn):
  cuerpo de la función
  return output
  Input In [1]
    def nombre_funcion(input1, input2, ..., inputn):
                                       ^
SyntaxError: invalid syntax

Observación 1. La instrucción return finaliza la ejecución de la función y devuelve el resultado que se indica a continuación. Si no se indicase nada, la función finalizaría, pero no retornaría nada.

Como hemos visto, en general, las funciones constan de 3 partes:

  • Inputs (parámetros o argumentos). Son los valores que le pasamos como entrada a la función.
  • Cuerpo. Son todas las operaciones que lleva a cabo la función.
  • Output. Es el resultado que devuelve la función.

Observación 2. Los parámetros son variables internas de la función. Si probásemos a ejecutar una de dichas variables en el entorno global, nos saltaría un error. Este tema lo trataremos más en detalle más adelante.

Con lo visto anteriormente, a la hora de construir una función hay que hacerse las siguientes preguntas:

  • ¿Qué datos necesita conocer la función? (inputs)
  • ¿Qué hace la función? (cuerpo)
  • ¿Qué devuelve? (output)

Observación 3. Los inputs y el output son opcionales: podemos definir una función sin necesidad de proporcionarle inputs y sin que nos devuelva nada. Una vez definida una función, para llamarla utilizamos su nombre seguido de paréntesis:

def mi_primera_funcion():
    print("Hola mundo")
mi_primera_funcion()
Hola mundo

Nuestra función mi_primera_funcion(), cuando es llamada, imprime “Hola mundo”, pero no devuelve absolutamente nada.

def saludar():
  return "Buenos dias"
saludar()
saludo=saludar()
print(saludo)
print(type(saludo))
Buenos dias
<class 'str'>

EJEMPLO 1#

Las funciones en Python, como en la mayoría de los lenguajes, usan una notación similar a la de las funciones matemáticas, con un nombre y uno o más argumentos entre paréntesis. Por ejemplo, ya usamos la función sum cuyo argumento es una lista o una tuple de números.

a = [1, 3.3, 5, 7.5, 2.2]
sum(a)
19.0
sum
<function sum>

En Python una función es un objeto, como con todos los objetos, podemos definir una variable y asignarle una función.

f=sum
help(f)
Help on built-in function sum in module builtins:

sum(iterable, start=0, /)
    Return the sum of a 'start' value (default: 0) plus an iterable of numbers
    
    When the iterable is empty, return the start value.
    This function is intended specifically for use with numeric values and may
    reject non-numeric types.
f(a)
19.0

También podemos crear un diccionario donde los valores sean funciones:

funciones={"suma":sum,"minimo":min,"maximo":max}
print("a =",a)
print("suma de a =",funciones["suma"](a))
print("minimo de a =",funciones["minimo"](a))
print("maximo de a =",funciones["maximo"](a))
a = [1, 3.3, 5, 7.5, 2.2]
suma de a = 19.0
minimo de a = 1
maximo de a = 7.5

EJEMPLO 2#

vamos a crear una función que nos calcule la división entera de dos números y nos retorne el cociente y el resto.

def division(x, y):
  div_exacta = x / y
  q = x // y
  r = x % y
  return div_exacta, q, r
division(450,20)
(22.5, 22, 10)
division(y=20,x=450)
(22.5, 22, 10)
div_exacta,cociente,residuo=division(450,20)
print("division exacta =",div_exacta)
print("cociente =",cociente)
print("residuo =",residuo)
division exacta = 22.5
cociente = 22
residuo = 10

VARIABLES DE LA FUNCIÓN#

Dentro de una función en Python existen dos tipos de variables:

  • Variable local. Aquella que es creada y solamente existe dentro de la función.
  • Variable global. Aquella que es creada en el entorno global.
Dada la siguiente función:
import math
def trigonometria(θ):
  θ=math.pi*θ/180
  seno = math.sin(θ)
  coseno = math.cos(θ)
  tangente = math.tan(θ)
  return seno,coseno,tangente
print("seno(θ) = {:.3}, coseno(θ) = {:.3}, tangente(θ) = {:.3}".format(*trigonometria(30)))
seno(θ) = 0.5, coseno(θ) = 0.866, tangente(θ) = 0.577

Si queremos imprimir el valor que toma la variable seno en el entorno global nos saltará un error, pues esta variable no existe a nivel global porque no ha sido declarada en dicho entorno ya que solamente ha sido declarada a nivel local, dentro de la función trigonometria().

print(seno)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-28-4aded4e0436b> in <module>()
----> 1 print(seno)

NameError: name 'seno' is not defined

Si dentro de una función utilizamos la palabra reservada global a una variable local, ésta automáticamente pasa a ser una variable global previamente definida.

def mult():
  global num
  num = 7
  mult = 2*num
  return mult

print(mult())
print(num)
14
7

PASO POR COPIA & PASO POR REFERENCIA

Dependiendo del tipo de dato que pasemos por parámetro a la función, podemos diferenciar entre:

  • Paso por copia. Se crea una copia local de la variable dentro de la función.
  • Paso por referencia. Se maneja directamnete la variable y los cambios realizados dentro de la función afectan también a nivel global.

En general, los tipos de datos básicos como enteros, flotantes, strings o booleanos se pasan por copia, mientras que estructuras de datos como listas, diccionarios, conjuntos o tuplas u otros objetos se pasan por referencia.

Un ejemplo de paso por copia sería:

def mitad(n):
    n = n/2
    return n
numero = 5
print(mitad(numero))
print(numero)
2.5
5

Un ejemplo de paso por referencia sería

def mitad_valores(numeros):
  for i in range(len(numeros)):
    numeros[i] /= 2
  return numeros
numeros = [1, 2, 3, 4, 5]
print(mitad_valores(numeros))
print(numeros)
[0.5, 1.0, 1.5, 2.0, 2.5]
[0.5, 1.0, 1.5, 2.0, 2.5]

Para evitar la modificación de la lista original, podemos hacerlo introduciendo por parámetro una copia de dicha lista

numeros = [1, 2, 3, 4, 5]
print(mitad_valores(numeros[:]))
print(numeros)
[0.5, 1.0, 1.5, 2.0, 2.5]
[1, 2, 3, 4, 5]

PARÁMETROS#

Por defecto, una función debe ser llamada con el número correcto de argumentos. Esto es, si la función espera 2 argumentos, tenemos que llamar a la función con esos 2 argumentos. Ni más, ni menos.

def camisa(talla, color):
  print("la camisa es talla",talla,"y color",color)
camisa("'M'","verde")
la camisa es talla 'M' y color verde
camisa("M")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-38-2d8a1c4ffa46> in <module>()
----> 1 camisa("M")

TypeError: camisa() missing 1 required positional argument: 'color'

NÚMERO NO DEFINIDO DE ARGUMENTOS#

Si no conocemos el número de parámetros que vamos a ingresar, entonces añadimos un asterisco (*) previo al nombre del parámetro en la definición de la función. Los valores introducidos serán guardados en una tupla.

def suma_numeros(*numero):
  suma=0
  for i in numero:
    suma=suma+i
  return suma
sum=suma_numeros(1,2,3)
print(sum)
6
numbers=[1,2,3,4,5,6,7,8,9,10]
print(suma_numeros(*numbers))
55

NÚMERO NO DEFINIDO DE LLAVES DE UN ARGUMENTO#

Definimos una funcion que imprima el nombre completo de una persona, los nombres completos pueden tener dos o incluso más apellidos, pero no sabemos si el usuario tiene 1 o 2 o más. Entones, podemos añadir dos asteriscos (**) antes del nombre del parámetro para así poder introducir tantos como queramos sin que la funcion nos devuelva un error

def nombre_completo(nombre, **apellido):
    print("El nombre completo es {}".format(nombre), end = " ")
    for i in apellido.items():
      print("{}".format(i[1]), end = " ")
nombre_completo(nombre = "Humberto", apellido = "Rojas")
El nombre completo es Humberto Rojas 
nombre_completo(nombre = "Humberto", apellido1 = "Rojas", apellido2 = "Huaroto")
El nombre completo es Humberto Rojas Huaroto 
nombre={"nombre":"humberto","apellido1":"rojas","apellido2":"huaroto"}

def nombre_completo(**nombre):
    print("El nombre completo es ", end = " ")
    for i in nombre.items():
      print("{}".format(i[1]), end = " ")

nombre_completo(**nombre)
El nombre completo es  humberto rojas huaroto 

ARGUMENTO POR DEFECTO#

Hemos visto que en Python una funcion puede tener o no parámetros, en caso de que tenga, podemos asignarle un valor por defecto.

Definimos la función potencia, que calcula el resultado de elevar el primer número al segundo número, le asignamos por defecto un valor de 2 al segundo número.

def potencia(x,y=2):
  return x**y
potencia(3,4)
81
potencia(4)
16
import math
def logaritmo(numero,base=10):
  return math.log(numero,base)
logaritmo(100)
2.0
def caida_libre(t, v0, h0, g=9.81):
  v = v0 + g*t
  h = h0 - v0*t - g*t**2/2
  return v,h
caida_libre(3,20,150)
(49.43, 45.855)

DOCSTRING#

Son comentarios explicativos que ayudan a comprender el funcionamiento de una función.

  • Van entre triple comilla doble
  • Pueden ser multilínea
  • Se sitúan al principio de la definición de la función

Retomando el ejemplo de caida libre, podríamos utilizar docstring del siguiente modo:

def caida_libre(t, h0, v0, g=9.81):
  """Devuelve la velocidad y la posición de una partícula en
  caída libre para condiciones iniciales dadas

  Parámetros
  ----------
  t : float
      el tiempo al que queremos realizar el cálculo
  h0: float 
      la altura inicial
  v0: float
      la velocidad inicial
  g : float (opcional)
      valor de la aceleración de la gravedad (default = 9.81)

  Returns
  -------
  (v,h):  tuple of floats
       v= v0 - g*t
       h= h0 - v0*t -g*t^2/2
  """
  v = v0 + g*t
  h = h0 - v0*t - g*t**2/2.
  return v,h
print(caida_libre.__doc__)
Devuelve la velocidad y la posición de una partícula en
  caída libre para condiciones iniciales dadas

  Parámetros
  ----------
  t : float
      el tiempo al que queremos realizar el cálculo
  h0: float 
      la altura inicial
  v0: float
      la velocidad inicial
  g : float (opcional)
      valor de la aceleración de la gravedad (default = 9.81)

  Returns
  -------
  (v,h):  tuple of floats
       v= v0 - g*t
       h= h0 - v0*t -g*t^2/2
  
help(caida_libre)
Help on function caida_libre in module __main__:

caida_libre(t, h0, v0, g=9.81)
    Devuelve la velocidad y la posición de una partícula en
    caída libre para condiciones iniciales dadas
    
    Parámetros
    ----------
    t : float
        el tiempo al que queremos realizar el cálculo
    h0: float 
        la altura inicial
    v0: float
        la velocidad inicial
    g : float (opcional)
        valor de la aceleración de la gravedad (default = 9.81)
    
    Returns
    -------
    (v,h):  tuple of floats
         v= v0 - g*t
         h= h0 - v0*t -g*t^2/2

EJEMPLOS DE FUNCIONES MÁS ELABORADAS#

""" Obtención de números primos."""

# Se importa la función sqrt.
from math import sqrt

# Función para evaluar si un número es primo.
def primo(numero):
    # Importa la función para obtener la raíz cuadrada.
    

    es_primo = True # Suponemos que SÍ es primo.
    divisor = 2     #Se inicia el ciclo con divisor = 2. 
                        
    # Se inicia un ciclo Mientras para buscar un divisor exacto.
    while divisor <= sqrt(numero) and es_primo:
        cociente = numero//divisor # División entera.
        if (numero == cociente*divisor):
            es_primo = False # Se encontró un divisor exacto.
        else:
            divisor = divisor + 1 # Se incrementa el divisor
    return (es_primo)

# Termina la función.

# INICIO DEL ALGORITMO PRINCIPAL

# Recibe el número a checar:
n = int(input("Dame un número entero: "))

 
es_primo = primo(n)
if (es_primo):
    print("SÍ es primo")
else:
    print("NO es primo")
                
# FIN
Dame un número entero: 37
SÍ es primo
""" Obtención de las raíces de una ecuación de segundo grado."""

# Se importa la función sqrt.
from math import sqrt

# Función para calcular la raíz cuadrada del discriminante.
def discriminante(a1, b1, c1):
    d = sqrt(b1*b1 - 4*a1*c1)
    return d
# Termina la función.

# Función para recibir los coeficientes.
def lectura( ):
    # Recibe los coeficientes:
    a = float(input("Dame el coeficiente de x**2: "))
    b = float(input("Dame el coeficiente de x: "))
    c = float(input("Dame el coeficiente independiente: ")) 
    return [a, b, c] # Los coeficientes están en una lista.
# Termina la función.

# Función para calcular las raíces.
def calcular(a, b, c, d1):
    # Calcula las raíces x1 y x2:
    # Se calculan las raíces:
    x1 = (-b + d1)/2/a
    x2 = (-b - d1)/2/a
    return (x1, x2) # Las raíces están en una tuplaa.
# Termina la función.


# INICIO DEL ALGORITMO PRINCIPAL

# Recibe los coeficientes:
[a, b, c] = lectura( )

# Se calcula el discriminante:
d1 = discriminante(a, b, c)

# Se calculan las raíces:
(x1, x2) = calcular(a, b, c, d1)

# Se despliegan las raíces:
print("La primera raíz es: ", x1)
print("La segunda raíz es: ", x2)

# FIN
Dame el coeficiente de x**2: 1
Dame el coeficiente de x: 12
Dame el coeficiente independiente: 35
La primera raíz es:  -5.0
La segunda raíz es:  -7.0
m=1
kg=1
s=1

## unidades derivadas

N=kg*m/s**2
tnf=9.81*N

g=9.81

a=9.81*N

b=a/tnf

print(b)
1.0