Una función es un bloque de código con un nombre asociado, que recibe 0 o más argumentos como entrada, sigue una serie de instrucciones, y devuelve un valor y/o realiza una tarea.
Python dispone de una serie de funciones integradas al lenguaje (built-in), y también permite crear funciones definidas por el usuario.
El uso de funciones es un componente muy importante de la programación estructurada, y tiene varias ventajas:
Devuelve un número entero, dependiendo del tipo de argumento o argumentos que reciba.
Si se ingresa un número de coma flotante (objeto tipo float), devuelve su parte entera.
int(2.5)
También puede devolver el entero correspondiente a una cadena de caracteres (objeto tipo string).
Por defecto, usa la base 10, en cuyo caso la cadena debe estar conformada sólo por números decimales.
int("23")
Pero también puede convertir cadenas en otras bases, si se explicita un segundo argumento. En ese caso, la cadena de caracteres debe ser coherente con una expresión numérica en la base.
int("10110101101", 2)
int("a0fc", 16)
int("3251", 8)
int("1012", 2)
Devuelve un número de coma flotante, y accepta argumentos de tipo numérico (int o float), o de tipo string que sean coherentes con un número entero o de coma flotante (cadenas de caracteres formadas por números y hasta un punto).
float(2)
float(2.5)
float("2")
float("2.5")
Uno de los cambios más notorios de Python2 a Python3 fue que la instrucción print fue convertida en una función.
print "Hola, Python"
print("Hola, Python")
Como función, print() recibe uno o más argumentos, que por defecto se imprimen en la salida estándar.
Los argumentos, si son más de uno, deben ir separados por comas.
print(1, 12, 123, "hola")
La función print() puede recibir también algunos argumentos ocpionales, que deberán necesariamente pasarse con su nombre.
print(1, 12, 123, "hola", sep='__')
Puede ser también un carácter extendido, como tabulador (\t) o salto de línea (\n).
print(1, 12, 123, "hola", sep='\t')
print(1, 12, 123, "hola", sep='\n')
print(1, 12, 123, "hola", end=' - ')
print("otra llamada a la función, en la misma línea")
Hay otros parámetros opcionales para la función print():
En los argumentos que se pasan a la función print() se pueden alternar cadenas de caracteres y variables:
operacion = "raíz cuadrada de dos"
valor = 2**0.5
print("el resultado de", operacion, "es:", valor)
Una forma más clara y elegante es referenciar objetos dentro de la misma cadena, y usar el método .format() para sustituirlos con los objetos que se le pasan como argumentos.
Los objetos se referencian con números entre llaves ({ }) dentro de la cadena (llamados campos de formato), y son sustituidos en el orden con que aparecen como argumentos de .format(), contando a partir de cero (argumentos posicionales).
operacion = "raíz cuadrada de dos"
valor = 2**0.5
print("el resultado de {0} es {1}".format(operacion, valor))
Los objetos también pueden ser referenciados por nombre (argumentos por clave).
operacion = "raíz cuadrada de dos"
print("el resultado de {nombre} es {resultado}".format(nombre=operacion, resultado=2**0.5))
En una misma llamada a la función print() pueden combinarse argumentos posicionales con argumentos por clave.
Opcionalmente se puede poner el signo de dos puntos después del número o nombre, y explicitar el tipo del objeto:
Esto permite controlar el formato de impresión del objeto. Por ejemplo, podemos utilizar la expresión .4f para determinar que un número de coma flotante (f) se imprima con cuatro dígitos después de la coma (.4).
operacion = "raíz cuadrada de dos"
valor = 2**0.5
print("el resultado de {0} es {resultado:.4f}".format(operacion, resultado=valor))
También puede aplicarse el operador % para dar formato a las cadenas.
La sintaxis es la siguiente:
operacion = "raíz cuadrada de dos"
valor = 2**0.5
print("el resultado de %s es %f" % (operacion, valor))
Con esta sintaxis hay que determinar el tipo del objeto:
También aquí se puede controlar el formato de salida. Por ejemplo, para obtener el valor con 8 dígitos después de la coma:
operacion = "raíz cuadrada de dos"
valor = 2**0.5
print("el resultado de %s es %.8f" % (operacion, valor))
Una discusión más completa del control de la salida de Python se encuentra en https://docs.python.org/3/tutorial/inputoutput.html
Como se vio en la clase 1, la función input() puede utilizarse para ingresar datos durante la ejecución del programa.
Opcionalmente, la función puede recibir un argumento, que de estar presente se imprime en la pantalla sin salto de línea final.
La función input() siempre devuelve un objeto de tipo str. Si el valor de entrada va a utilizarse como un número, deberá hacerse la conversión explícitamente.
entrada = int(input("ingrese un número entero: "))
print(entrada**2)
Devuelve el valor absoluto de un número (entero o de coma flotante).
abs(3)
abs(-3)
abs(-2.5)
Recibe como argumento un entero, y devuelve una cadena con el carácter cuyo código Unicode corresponde a ese valor. El rango válido para el argumento es de 0 a 1114111.
chr(97)
chr(934)
chr(1044)
chr(19989)
chr(43457)
Debe recibir dos argumentos numéricos, y devuelve dos valores: resultado de la división entera, y el resto.
divmod(22, 4)
Invoca el sistema integrado de ayuda, devolviendo información acerca del objeto que recibe como argumento.
help(divmod)
Convierte un número entero a una cadena en base hexadecimal, antecedida del prefijo '0x'.
hex(16)
hex(127)
Devuelve la longitud (cantidad de elementos) de un objeto. Puede ser una cadena de caracteres, o alguno de los otros tipos de secuencia o colección todavía no vistos.
len("Hola, Python")
len("0123456789")
Si recibe más de un argumento, devuelve el mayor de ellos.
max(23, 12, 145, 88)
max("a", "Z")
Si recibe un solo argumento, devuelve el mayor de sus elementos. Debe ser un objeto iterable; puede ser una cadena de caracteres, o alguno de los otros tipos de secuencia o colección todavía no vistos.
max("Hola, Python")
Tiene un comportamiento similar a max(), pero devuelve el mínimo.
min(23, 12, 145, 88)
min("Hola, Python")
Convierte un número entero en una cadena en base octal, antecedida del prefijo '0o'.
oct(8)
oct(123)
Es el inverso de chr(): dada una cadena representando un carácter Unicode, devuelve el entero del código correspondiente.
ord('w')
Como argumento se puede ingresar el carácter literalmente, o su correspondiente código Unicode, antecedido del prefijo ''.
ord('丕')
ord("\u4e15")
Si recibe dos argumentos, eleva el primero a la potencia del segundo.
pow(2, 3)
pow(10, 2)
pow(10, -2)
Si recibe un tercer argumento opcional, éste funciona como módulo.
pow(2, 3, 3)
Si recibe un argumento numérico, devuelve el entero más próximo (a diferencia de int(), que trunca a la parte entera.
round(2.3)
round(2.8)
round(-2.8)
round(2.5)
Si se agrega un segundo parámetro opcional, se puede determinar la cantidad de cifras después de la coma (por defecto, cero).
a = 2**(0.5)
print(a)
print(round(a))
print(round(a, 2))
print(round(a, 4))
print(round(a, 8))
Devuelve el tipo del objeto que recibe como argumento.
type(2)
type(2.3)
type("hola")
type(int)
Para crear una función es esencial definir claramente qué queremos que haga.
Es decir: - qué queremos ingresar a la función como argumento(s) - qué queremos que devuelva o haga la función
Vamos a crear una función que convierta un valor de temperatura en grados Fahrenheit a grados Celsius (ver Ejemplo 1.1)
La función va a tener un único argumento, que es el valor de temperatura en Fahrenheit, y va a devolver el valor en grados Celsius.
def fahrenheit_to_celsius(grados_fahrenheit):
grados_celsius = (grados_fahrenheit-32)*5/9
return grados_celsius
temp1 = fahrenheit_to_celsius(80)
print(temp1)
print(fahrenheit_to_celsius(66))
temp2 = 75
print(fahrenheit_to_celsius(temp2))
Vamos a crear una función que, partir de una frecuencia dada, calcule la frecuencia a un número determinado de cents de distancia (ver Ejemplo 1.2).
def cents_a_frecuencia(frec_inicial, cents):
frec_final = frec_inicial*(2**(cents/1200))
return frec_final
frec1 = 440
frec2 = cents_a_frecuencia(frec1, 50)
print(frec2)
frec3 = cents_a_frecuencia(frec1, -1200)
print(frec3)
Vamos a definir una función que, dado un número de divisiones iguales de un intervalo "octavante" (no necesariamente 2), calcule el multiplicador de frecuencia entre grados sucesivos (por ejemplo, para la división en 12 partes iguales de la octava 2:1, el valor 1.0594630943592953). (ver Ejercicio 1.1)
Solución: Para una cantidad N de divisiones de un intervalo O, el valor del multiplicador de frecuencia entre grados conjuntos es raíz N-ésima de O.
def division(grados, octava):
factor = octava**(1/grados)
return factor
et12 = division(12, 2)
print(et12)
et19 = division(19, 2)
print(et19)
foo = division(23, 3)
print(foo)
Por defecto, los argumentos que se pasan a la función son interpretados en el orden en que están los parámetros en la definición (argumentos posicionales). Pero se pueden pasar los argumentos en cualquier orden arbitrario, usando los nombres de los parámetros (argumentos por clave).
et12 = division(octava=2, grados=12)
print(et12)
En una función podemos determinar que un parámetro sea opcional y adquiera un valor por defecto, asignándole un valor en la definición de la función.
Por ejemplo, en la función anterior podemos decidir que por defecto el valor de octava es 2, y sólo necesitamos explicitar ese parámetro cuando queremos un valor diferente.
def division(grados, octava=2):
factor = octava**(1/grados)
return factor
et12 = division(12)
print(et12)
et19 = division(19)
print(et19)
foo = division(23,3)
print(foo)
Por defecto, las variables en Python son locales. Esto quiere decir que las variables definidas y utilizadas en el bloque de código de una función, sólo tienen existencia dentro de la misma, y no interfieren con otras variables del resto del código.
A su vez, las variables existentes fuera de una función, no son visibles dentro de la misma.
En caso de que sea conveniente o necesario, una variable puede convertirse en global declarándola explícitamente como tal con la instrucción global.
var1 = "variable original"
def globvar():
global var1
var1 = "variable global modificada"
print(var1)
globvar()
print(var1)
Como se puede ver, después de llamar a la función globvar(), la variable var1 queda modificada.
En general, este procedimiento debe utilizarse con precaución.
Las docstrings (o documentation strings) son, como lo dice su nombre, cadenas de texto que sirven para documentar diversos aspectos de una función: qué hace, el valor de sus parámetros, qué tipos de argumentos recibe, qué tipo de objeto devuelve, etc.
Aparecen como primera instrucción en el cuerpo de la función, a continuación de su declaración, y por convención van delimitadas por triple comillas.
def fahrenheit_to_celsius(grados_fahrenheit):
"""convierte una temperatura en grados Fahrenheit a grados Celsius"""
grados_celsius = (grados_fahrenheit-32)*5/9
return grados_celsius
En casos simples, la doctring consiste en una sola línea, con una descripción sumaria de la función.
Funciones más complejas pueden requerir una descripción más detallada. En ese caso, por convención se deja una línea en blanco después de la primera línea con la descripción sumaria, y luego se procede a expandir la descripción.
Una funcionalidad valiosa de las docstrings, es que Python genera a partir de ellas su propia documentación, que se puede invocar en línea mediante la función help() vista más arriba.
help(fahrenheit_to_celsius)
Al invocar la función help() pasándole como argumento el nombre de una función, nos devuelve la siguiente información:
Se pueden definir funciones que no tengan parámetros de entrada. En ese caso, la función ejecuta el mismo código cada vez que es invocada.
def alarma():
print("riiiiiiiiing")
alarma()
La función anterior tampoco utiliza la intrucción return para devolver un valor.
En realidad, toda función en Python devuelve un valor. Cuando no se utiliza la la instrucción return para devolver un valor explícito, la función devuelve el valor None.
valor = alarma()
print("El valor que devuelve la función alarma() es", valor)
Los comentarios en el código tienen una vital importancia en el desarrollo de todo programa.
Son ignorados por el intérprete y no generan ningún tipo de código, pero constituyen una ayuda esencial tanto para quien está desarrollando el programa, como para otras personas que lean el código.
Entre otras, algunas de las funciones más importantes que pueden cumplir los comentarios en un programa, son:
El signo para indicar el comienzo de un comentario en Python es la almohadilla o numeral (#), a partir del cual y hasta el fin de la línea, todo se considera un comentario y es ignorado por el intérprete.
El carácter # puede estar al comienzo de línea (en cuyo caso toda la línea será ignorada), o después de finalizar una instrucción válida de código.
Como ejemplo, se muestra una forma posible de comentar el programa del Ejemplo 1.2 (clase 1).
# programa que calcula la frecuencia resultante al transportar
# una frecuencia dada una cierta cantidad de semitonos
# primero se pide al usuario que ingrese la frecuencia incial
# y la cantidad de cents a ser transportada
frec_inicial = int(input("ingrese la frecuencia inicial: ")) # se convierte el string de entrada en un entero
cents = int(input("ingrese la cantidad de cents: "))
frec_final = frec_inicial*(2**(cents/1200)) # se calcula la frecuencia resultante
print("frecuencia final: ", frec_final)
En un programa tan corto y sencillo quizás no sean necesarios tantos comentarios. Es importante escribir programas suficientemente comentados, pero no recargar el código con comentarios innecesarios de cosas obvias.
Por ejemplo, el comentario siguiente sería inadecuado, por resultar obvio de la propia instrucción:
print("frecuencia final: ", frec_final) # imprime la frecuencia resultante en la pantalla
A diferencia de otros lenguajes de programación, Python no dispone de un método para delimitar bloques de comentarios de varias líneas.
Las alternativas para introducir comentarios multilíneas son: