Funciones
Contents
2.1. Funciones#
2.1.1. Enlaces#
2.1.2. Funciones con parámetros y retorno#
def funcion_1(x):
"""
Esto se llama en inglés "docstring". Sirve para explicar lo que hace la función,
cualquier información que pueda ser útil al usuario y a quién la haya creado
x: número (real o entero)
función_1: valor de x**2 - 1
"""
resultado = x**2 -1
return resultado
funcion_1(2)
3
funcion_1()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [3], in <cell line: 1>()
----> 1 funcion_1()
TypeError: funcion_1() missing 1 required positional argument: 'x'
funcion_1
<function __main__.funcion_1(x)>
type(funcion_1(2.))
float
def funcion_2(a,b,c):
"""
a,b,c: números
funcion_2: suma de cuadrados de a, b y c
"""
return a**2 + b**2 + c**2
funcion_2(1,2,1)
6
def funcion_3(cadena):
"""
cadena: str
funcion_3: devuelve True o False según tenga cadena más de tres caracteres o no
"""
if len(cadena) > 3:
return True
else:
return False
funcion_3('estudios')
True
type(funcion_3('estudios'))
bool
def funcion_4(palabra, letra):
"""
palabra: str, cadena de texto
letra: str, una letra
funcion_4: devuelve una nueva palabra donde se han cambiado las vocales por letra
"""
rsltd = ''
vocales = 'aeiouáéíóúüAEIOUÁÉÍÚÜ'
for s in palabra:
if s in vocales:
rsltd += letra
else:
rsltd += s
return rsltd
funcion_4('barco','s')
'bsrcs'
type(funcion_4('barco','s'))
str
2.1.3. Funciones sin paramétros y sin retorno#
def funcion_5():
"""
Imprime '¡Hola Mundo!'
"""
print('¡Hola Mundo!')
funcion_5()
¡Hola Mundo!
a = funcion_5()
¡Hola Mundo!
a
type(a)
NoneType
def funcion_6():
"""
Dibuja un rectángulo con asteriscos
"""
for i in range(8):
print('* '*8)
funcion_6()
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
type(funcion_6())
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
NoneType
2.1.4. Funciones sin paramétros y con retorno#
def funcion_7():
"""
devuelve ¡Hola!
"""
rsltd = '¡Hola!'
return rsltd
funcion_7()
'¡Hola!'
type(funcion_7())
str
2.1.5. Ámbito de las variables definidas dentro de funciones#
Las variables definidas dentro de una función solo tienen existencia en el espacio de nombres de esa función
def funcion_8():
i = 1
j = i + 1
print(j)
funcion_8()
2
i
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [27], in <cell line: 1>()
----> 1 i
NameError: name 'i' is not defined
j
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [28], in <cell line: 1>()
----> 1 j
NameError: name 'j' is not defined
Cuando se invoca una función se crea un espacio de nombres propio de esa función. De esta forma no se produce ningún problema si en el interior de varias funciones hemos utilizado el mismo nombre para variables que se comportan de forma distinta en cada función.
Si un variable se utiliza dentro de una función y no se ha inicializado dentro de la función, antes de producir un error, Python busca fuera del espacio de nombres de la función para ver si está definida en el espacio de nombres que se abre cuando se lanza Python. Podríamos llamar a éste, el espacio general de nombres de Python. Observad que cada vez que se cierra Python se cierra este espacio general de nombres y todos los espacios de nombres generados cada vez que se invoca una función. Al abrir Python de nuevo se genera un nuevo espacio general de nombres, que no hereda nada del anterior, ya que es el espacio de la anterior sesión ha desaparecido junto con todos los espacios de nombres que se hayan generado cada vez que se invoca una función.
En resumen: Una variable definida en el cuerpo de una función solo tiene existencia en el espacio de nombres de esa función. Pero todas las funciones pueden usar variables del espacio de nombres general de Python, siempre y cuando no cambien su valor.
En el caso de abajo no hay problema
a = 3
def funcion_9():
b = a + 1
print(b)
funcion_9()
4
a
3
b
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [32], in <cell line: 1>()
----> 1 b
NameError: name 'b' is not defined
Pero en este caso de abajo hay un problema ya que no se puede modificar el valos de a
en el cuerpo de la función:
a = 5
def funcion_10():
a = a + 1
return a
funcion_10()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Input In [34], in <cell line: 1>()
----> 1 funcion_10()
Input In [33], in funcion_10()
3 def funcion_10():
----> 4 a = a + 1
5 return a
UnboundLocalError: local variable 'a' referenced before assignment
Sin embargo en el ejemplo de abajo no hay problema ya que hay una variable b
en el espacio de la función que por lo tanto es diferente del la variable b
del espacio generla de nombres:
b = 5
def funcion_11(x):
b = x
return x + 1
funcion_11(2)
3
b
5
Si definimos una variable dentro de una función, no estará disponible fuera:
def funcion_12(x,y):
aux = x % y
return aux
funcion_12(13,5)
3
aux
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [40], in <cell line: 1>()
----> 1 aux
NameError: name 'aux' is not defined
Si queremos que la variable aux esté disponible fuera de la función funcion_12 debemos definirla como variable global:
def funcion_13(x,y):
global aux
aux = x % y
return aux
funcion_13(13,5)
3
aux
3
Otros cuatro ejemplos para ilustrar el ámbito de las variables definidas dentro de una función. Primer caso:
def f(y):
x = 1
x += 1
print(x)
x = 5
f(x)
print(x)
2
5
Segundo caso:
def g(y):
print(x)
print(x + 1)
x = 5
g(x)
print(x)
5
6
5
Tercer caso:
def h(x):
x = x + 1
x = 5
h(x)
print(x)
5
Cuarto caso:
def k(x):
x = x + 1
y = y + 1
return x, y
x = 5
y = 1
k(x)
print(x)
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Input In [51], in <cell line: 3>()
1 x = 5
2 y = 1
----> 3 k(x)
4 print(x)
Input In [50], in k(x)
1 def k(x):
2 x = x + 1
----> 3 y = y + 1
4 return x, y
UnboundLocalError: local variable 'y' referenced before assignment
2.1.6. Uso de una función en el cuerpo de otra#
2.1.6.1. Ejemplos#
Ejemplo 1
def u(x):
if x != 0:
return x**3 + 2*x
else:
return 5
def w_1(x):
return x + u(x)
w_1(1)
4
Ejemplo 2
Ahora definimos una solo función en cuyo cuerpo hay otra función. Vermos que estos dos procedimientos dan el mismo resultado.
def w_2(x):
def u(x):
if x != 0:
return x**3 + 2*x
else:
return 5
return x + u(x)
w_2(1)
4
Las funciones anteriores w_1()
y w_2()
hacen lo mismo
for n in range(-7, 7):
if w_1(n) != w_2(n):
print('Horror')
else:
print('Todo va bien')
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
Todo va bien
def comprobación(f, g):
"""
Con esto podemos comprobar que las dos funciones devuelven los mismos valores
si los parámetros toman como valores, número enteros
"""
diferentes = False
for n in range(-20, 20):
if f(n) != g(n):
diferentes = True
break
if diferentes:
print('Horror')
else:
print('Todo va bien')
comprobación(w_1, w_2)
Todo va bien
2.1.6.2. Composición de funciones#
2.1.6.2.1. Ejemplo#
def f(x):
return x + 1
def g(x):
return 3*x
g(f(2))
9
f(3 + g(-1))
1
2.1.7. Parámetros: orden, posición y valores#
El orden en que se escriben los parámetros se puede cambiar
Definimos la siguiente función que depende de tres parámetros:
def subintervalos(N,a,b):
"""
N: int
a,b: float o int
funcion_12: sin retorno. Divide el intervalo (a,b) en N subintervalos iguales y
los imprime
"""
h = (b-a)/N
for k in range(N):
print('(' + str(a + h*k) + ',' + str(a + h*(k+1)) + ')')
subintervalos(20,1,2)
(1.0,1.05)
(1.05,1.1)
(1.1,1.15)
(1.15,1.2)
(1.2,1.25)
(1.25,1.3)
(1.3,1.35)
(1.35,1.4)
(1.4,1.45)
(1.45,1.5)
(1.5,1.55)
(1.55,1.6)
(1.6,1.65)
(1.65,1.7000000000000002)
(1.7000000000000002,1.75)
(1.75,1.8)
(1.8,1.85)
(1.85,1.9)
(1.9,1.9500000000000002)
(1.9500000000000002,2.0)
Cuando se utilizan los parámetros de una función sin indicar su nombre se habla de parámetros posicionales ( positional parameters ). Si variamos de orden los valores (20, 1, 2)
obtendremos cosas distintas al invocar la función.
También se puede escribir
subintervalos(b = 2, N = 20, a = 1)
(1.0,1.05)
(1.05,1.1)
(1.1,1.15)
(1.15,1.2)
(1.2,1.25)
(1.25,1.3)
(1.3,1.35)
(1.35,1.4)
(1.4,1.45)
(1.45,1.5)
(1.5,1.55)
(1.55,1.6)
(1.6,1.65)
(1.65,1.7000000000000002)
(1.7000000000000002,1.75)
(1.75,1.8)
(1.8,1.85)
(1.85,1.9)
(1.9,1.9500000000000002)
(1.9500000000000002,2.0)
Cuando se utilizan los parámetros de una función indicando su nombre se habla de parámetros referenciales ( keywords arguments ). De esta forma podemos utilizar cualquier orden para introducir los parámetros.
2.1.7.1. Parámetros con valores por defecto#
En la siguiente función, el parámetro N
toma el valor 20
por defecto. Son los parámetros por defecto
def subintervalos_p(a,b, N = 20):
"""
N: int
a,b: float o int
funcion_12: sin retorno. Divide el intervalo (a,b) en N subintervalos iguales y
los imprime
"""
h = (b-a)/N
for k in range(N):
print('(' + str(a + h*k) + ',' + str(a + h*(k+1)) + ')')
Esto significa que si solo indicamos el valor de dos parámetros, Python le dará el valor 20
a N
. Los otros dos parámetros se asignarán por orden, el primero a a
y el segundo a b
.
subintervalos_p(1,2)
(1.0,1.05)
(1.05,1.1)
(1.1,1.15)
(1.15,1.2)
(1.2,1.25)
(1.25,1.3)
(1.3,1.35)
(1.35,1.4)
(1.4,1.45)
(1.45,1.5)
(1.5,1.55)
(1.55,1.6)
(1.6,1.65)
(1.65,1.7000000000000002)
(1.7000000000000002,1.75)
(1.75,1.8)
(1.8,1.85)
(1.85,1.9)
(1.9,1.9500000000000002)
(1.9500000000000002,2.0)
Pero también podemos suministrar un valor específico para N
mediante el uso referenciales del parámetro. Por ejemplo:
subintervalos_p(1,2,N = 10)
(1.0,1.1)
(1.1,1.2)
(1.2,1.3)
(1.3,1.4)
(1.4,1.5)
(1.5,1.6)
(1.6,1.7000000000000002)
(1.7000000000000002,1.8)
(1.8,1.9)
(1.9,2.0)
Como ya hemos visto, los parámetros como a
y b
son posicionales y N
sería un parámetro referencial. De esta forma hemos cambiado el valor por defecto de N
.
Los parámetros referenciales siempre deben de ir al final. En caso contrario tendremos un error
subintervalos_p(1,N=10,2)
Input In [68]
subintervalos_p(1,N=10,2)
^
SyntaxError: positional argument follows keyword argument
subintervalos_p(N=10, 1, 2)
Input In [69]
subintervalos_p(N=10, 1, 2)
^
SyntaxError: positional argument follows keyword argument
2.1.8. Ejemplos#
2.1.8.1. Ejemplo#
Escribe la función saludo()
que devuelve “Buenos dias”
def saludo1():
return "Buenos días"
saludo1()
'Buenos días'
2.1.8.2. Ejemplo#
Escribe la función saludo2(x)
que devuelve “Buenos dias x”, donde x
es una cadena
def saludo2(x):
s="Buenos días "+x
return s
saludo2("Luis")
'Buenos días Luis'
2.1.8.3. Ejemplo#
Escribe la función metroscentimetros(x)
devuelve x metros en centímetros donde x
es un número
def metroscentimetros(x):
return x*100
metroscentimetros(15)
1500
2.1.8.4. Ejemplo#
Escribe la función centigrkelvin(x)
que devuelve xºC en ºK donde x
es un número
def centigrkelvin(x):
return x+273.15
centigrkelvin(0)
273.15
2.1.8.5. Ejemplo#
Escribe la función long(x)
que cuenta los caracteres de una cadena x
def long(x):
contador=0
for i in x:
contador+=1
return contador
long("mi cadena")
9
2.1.8.6. Ejemplo#
Escribe la función reemplazar(texto, letra, nletra)
que reemplaza el caracter letra
por nletra
en la cadena texto
def reemplazar(texto, letra, nletra):
ntexto=""
for l in texto:
if l==letra:
ntexto+=nletra
else:
ntexto+=l
return ntexto
reemplazar("mi cadena",nletra="***",letra="a")
'mi c***den***'
reemplazar(saludo1(),nletra="***",letra="a")
'Buenos dí***s'
2.1.8.7. Ejemplo#
Escribe la función sinacentos1(texto)
que devuelve una cadena de letras minúsculas sin acentos. La variable texto
es una cadena de letras minúsculas.
def sinacentos1(texto):
ntexto=""
for letra in texto:
if letra=="á":
ntexto+="a"
elif letra=="é":
ntexto+="e"
elif letra=="í":
ntexto+="i"
elif letra=="ó":
ntexto+="o"
elif letra=="ú":
ntexto+="u"
else:
ntexto+=letra
return ntexto
sinacentos1("adéúdé")
'adeude'
Otra versión de sinacentos(texto)
def sinacentos2(texto):
conAcentos = 'áéíóúü'
sinAcentos = 'aeiouu'
for i in range(len(conAcentos)):
nuevo_texto = ''
for s in texto:
#print(i,s)
if s == conAcentos[i]:
nuevo_texto += sinAcentos[i]
else:
nuevo_texto += s
#print(nuevo_texto)
texto=nuevo_texto
return texto
sinacentos2("además")
'ademas'
La última versión de sinacentos(texto)
utilizando la función reemplazar()
que creamos más arriba
def sinacentos3(texto):
st="áéíóú"
s="aeiou"
for i in range(5):
if st[i] in texto:
texto = reemplazar(texto,st[i],s[i])
return texto
sinacentos3("además")
'ademas'
2.1.8.8. Ejemplo#
Ámbito de una variable: Utilizamos una variable x
en la función g, en la función h y en el programa principal ¿qué ocurre?
Caso 1
def g1(x):
def h():
x = 'abc'
x = x + 1
print('En g1(x): x =', x)
h()
return x
x = 3
z = g1(x)
En g1(x): x = 4
x
3
z
4
Caso 2
def g2(x):
def h():
x = 'abc'
return x
x = x + 1
print('En g2(x): x =', x)
return h()
x = 3
z = g2(x)
En g2(x): x = 4
x
3
z
'abc'
Ponemos un print()
en el cuerpo de la función h()
para ver que está pasando
def g3(x):
def h():
x = 'abc'
print('En h(): x =', x)
return x
x = x + 1
print('En g3(x): x =', x)
return h()
z = g3(3)
En g3(x): x = 4
En h(): x = abc
x
3
z
'abc'
2.1.8.9. Ejemplo#
Escribe la función bisiesto(año)
que devuelve True
o False
si el año es bisiesto o no, donde año
es un entero
def bisiesto(año):
"""
año - número que corresponde a un año
Devuelve True o False si el año es bisiesto o no
"""
return (año%4 == 0)
bisiesto(2020)
True
bisiesto(2019)
False
2.1.8.10. Ejemplo#
Escribe la función dias(año)
que devuelve el número de días de un año. La variable año
es entera.
def dias(año):
if bisiesto(año):
return 366
else:
return 365
dias(2020)
366
dias(2019)
365
def bisiesto(año):
"""
año - número que corresponde a un año
Devuelve True o False si el año es bisiesto o no
"""
return (año%4 == 0)
def dias(año):
if bisiesto(año):
return 366
else:
return 365
def dias(año):
def bisiesto(año):
"""
año - número que corresponde a un año
Devuelve True o False si el año es bisiesto o no
"""
return (año%4 == 0)
if bisiesto(año):
return 366
else:
return 365
2.1.8.11. Ejemplo#
Escribe la función mayor(nombre1,edad1,nombre2,edad2)
que compara edad1
y edad2
e imprime lo siguiente:
Ejemplos:
mayor('Juan',18, 'Ana', 15)
imprime Juan es 3 años mayor que Ana
mayor('Juan',18, 'Ana', 18)
imprime Juan y Ana tienen la misma edad
def mayor(nombre1,edad1,nombre2,edad2):
if edad1 > edad2:
print(nombre1 + ' es ' + str(edad1 - edad2) + ' años mayor que ' + nombre2)
elif edad2 > edad1:
print(nombre2 + ' es ' + str(edad2 - edad1) + ' años mayor que ' + nombre1)
else:
print(nombre1 + ' y ' + nombre2 + ' tienen la misma edad')
mayor('Juan',24, 'Ana', 24)
Juan y Ana tienen la misma edad
2.1.8.12. Ejemplo#
Escribe la función primer_elemento(I)
que devuelve el primer elemento del iterable I
def primer_elemento(I):
"""
I - iterable arbitrario
devuelve el primer elemento de I
"""
for u in I:
return u
I = 'ahora'
primer_elemento(I)
'a'
primer_elemento(range(8,24))
8
2.1.8.13. Ejemplo#
Escribe la función suma(m,n)
que devuelve la suma de los números enteros de m
a n
ambos inclusive. En caso de que m
sea mayor que n
no debe devolver nada.
def suma(m,n):
if m <= n:
suma = 0
for u in range(m, n + 1):
suma += u
return suma
suma(1,3)
6
suma(3,1)
2.1.8.14. Ejemplo#
Escriba la función juego()
que escoge un número entre 1 y 6, ambos inclusive, pero no nos lo dice. Nos pide un número por teclado y si es correcto imprime Has acertado. En caso contrario, imprime No has acertado. Prueba otra vez y nos da la posiblidad de volver a decir un número.
Aquí se puede utilizar la función randint()
que no es una función propia de Python, pertence al módulo random
. Esta función proporciona números aleatorios.
Después define la función juego(N)
que inicia un juego como el de antes para los números del \(1\) al \(N,\) ambos inclusive.
def juego():
from random import randint # así podemos utilizar la funcíon randint() del módulo random
N = randint(1,6)
while True:
n = int(input('Di un número entre 1 y 6 :'))
if n == N:
print('Has acertado')
break
else:
print('No has acertado. Prueba otra vez')
print()
juego()
def Juego(K):
from random import randint
N = randint(1,K)
while True:
n = int(input('Di un número entre 1 y ' + str(K) + ': '))
if n == N:
print('Has acertado')
break
else:
print('No has acertado. Prueba otra vez')
print()
Juego(10)
2.1.9. Ejercicios#
Definir las siguientes funciones que realizan las tareas indicadas a continuación:
bienvenida(): imprime el mensaje
Bienvenido a Python
.f(x): devuelve el valor de \(x^3 - 3x^2 + 1\) para un número
n
.potencia_numero(n,m): devuelve \(n\) elevado a \(m,\) donde \(n\) y \(m\) son enteros.
suma_digitos(n): devuelve la suma de los dígitos del número entero
n
.Ejemplo: la llamada
suma_digitos(631)
devuelve el entero10
.
compara(x,y): devuelve \(0\) si \(x=y\), \(1\) si \(x>y\), \(-1\) si \(x<y\).
Ejemplo: la llamada
compara(3,2)
devuelve1
punto_medio(a,b): devuelve el punto medio del intervalo \((a,b)\).
semintervalo_izq(a,b): devuelve el semintervalo (mitad) izquierdo del intervalo \((a,b)\).
Ejemplo: la llamada
semintervalo_izquierdo(0,2)
devuelve(0,1)
semintervalo_der(a,b): devuelve el semintervalo (mitad) derecho del intervalo \((a,b)\).
pertenece(N,a,b): devuelve
True
oFalse
según \(N\) pertenezca o no al intervalo \((a,b)\).divide_mitad(N,a,b): devuelve el semintervalo de \((a,b)\) donde se encuentra \(N\). Si \(N\) no pertenece al intervalo, devuelve
N no está en el intervalo
.Ejemplo: la llamada
divide_mitad(17, 0, 100)
devuelve(0,50)
Ejemplo: la llamada
divide_mitad(65, 0, 100)
devuelve(50,100)
Ejemplo: la llamada
divide_mitad(165, 0, 100)
devuelve165 no etá en el intervalo
zoom(palabra): devuelve la palabra en mayúsculas y con sus letras separadas por un espacio.
Ejemplo: la llamada
zoom(‘sandwich’)
devuelve la cadenaS A N D W I C H
mayor2(a,b): devuelve el máximo de los números \(a,b\).
mayor3(a,b,c): devuelve el máximo de los números \(a,b,c\).
maximo4(a,b,c,d) que devuelve el máximo de los números \(a, b, c\) y \(d.\)
rectangulo(n,m): dibuja un rectángulo con el símbolo
0
de ancho \(n\) y alto \(m,\) donde \(n\) y \(m\) son enteros.factorial(n): devuelve el factorial del entero no negativo \(n\).
alfa(cadena): devuelve una cadena en la que se han cambiado las tres primeras letras
a
decadena
porA
.suma_cuadrados_2(a,b,c,d): devuelve la suma de los cuadrados de los dos números más grandes entre \(a,b,c,d\).
Ejemplo: la llamada
suma_cuadrados_2(2,4,1,6)
devuelve52
(\(= 4^2 + 6^2\)).
frecuencia(texto,letra): devuelve el número de veces que aparece letra en texto.
Ejemplo: la llamada
frecuencia(‘vaca’, ‘a’)
devuelve2
.Ejemplo: la llamada
frecuencia(‘vaca’, ‘q’)
devuelve0
.
esta_ordenado(cadena): devuelve
True
oFalse
según las letras decadena
estén ordenados alfabéticamente o no, suponiendo que las letras decadena
son minúsculas y no tienen tildes.mi_max(cadena): devuelve el mayor de los caracteres de
cadena
que está formada por letras minúsculas sin acentos.Ejemplo: la llamada
mi_max('una vaca asturiana')
devuelvev
sin_tildes(cadena): devuelve una cadena que corresponde a quitar las tildes de las vocales de
cadena
.Ejemplo: la llamada
sin_tildes('un relámpago iluminó el cielo')
devuelveun relampago ilumino el cielo
letra_mas_frecuente(cadena): devuelve la letra más frecuente en el texto
cadena
.dinamica(n,f,a): devuelve el \(n\)-ésimo término de la sucesión definida por
donde \(a\) es un número real y \(f\) una función.