01 - Manual Alumno - Python
01 - Manual Alumno - Python
Operaciones de entrada y
salida
Funciones
Las funciones permiten agrupar un bloque de código o conjunto de instrucciones.
Opcionalmente reciben uno o más argumentos y retornan un valor. En Python, para crear
una función empleamos la palabra reservada def seguido de su nombre y sus parámetros
entre paréntesis, en caso de tener. A continuación se coloca su contenido utilizando una
indentación de 4 espacios.
def f():
pass
La función anterior literalmente no hace nada. La palabra reservada pass se utiliza para
rellenar un bloque de código que es requerido sintácticamente (no podría estar vacío porque
lanzaría un error de sintaxis).
Hemos creado una función con el nombre sumar con dos parámetros de nombres a y b, y
que retorna el resultado de la suma de ambos. Como se trata de una función pequeña
podemos escribirla también en la consola interactiva, se vería más o menos así:
>>> sumar(7, 5)
12
Para indicar parámetros opcionales, indicamos su valor por defecto con el signo de igual
(=).
(Nótese que, por convención, cuando indicamos valores por defectos en la definición de una
función no se colocan espacios alrededor del signo de igual).
Los argumentos con valores por defecto siempre deben ir al final de la función. Por ejemplo,
el siguiente código es inválido:
Cuando una función no retorna ningún valor (es decir, no incluye la palabra reservada
return), por defecto retorna None.
A los argumentos con valores por defecto se los conoce como keyword arguments o
“argumentos por nombre”, ya que al llamar a la función se puede especificar su valor
indicando su nombre. Por ejemplo:
Esto permite que, en la segunda llamada, a mantenga su valor por defecto mientras que b
obtenga el número 50. En el caso que se especifiquen ambos argumentos, indicar o no su
nombre es indistinto.
>>> sumar(7, 5)
12
>>> sumar(a=7, b=5)
12
Al definir una función generalmente se le añade un una cadena entre comillas triples (otra
forma válida de crear textos en Python) indicando qué es lo que hace.
La razón por la que se utiliza una cadena y no un comentario es que dicha información es
automáticamente almacenada por Python en un atributo de la función (veremos con detalle
más adelante). Por ejemplo, podemos acceder al docstring de nuestra función vía:
help(sumar)
Por último, en Python es también posible crear funciones anónimas o lambda. Sin embargo,
por lo general es más conveniente crear funciones convencionales, por lo que únicamente
las mencionamos al pasar.
Habíamos visto cómo crear una cadena de caracteres utilizando comillas dobles o simples.
Sin embargo es bastante usual tener que incluir otros tipos de datos dentro de una cadena.
Para esto utilizamos la función format(). Por ejemplo:
En el código creamos una cadena en donde queremos incluir los objetos nombre y edad
(una cadena y un entero, respectivamente). En su lugar, colocamos {0} y {1} (y así
sucesivamente en relación con la cantidad de objetos que queramos incluir) y por último
llamamos a format() pasándole como argumentos los elementos que queremos insertar
dentro de mensaje.
Nótese que las cadenas en Python son objetos inmutables, por lo que format() retorna
una nueva cadena con los valores reemplazados.
A partir de la versión 3.6 Python introduce un método más legible, que consiste en poner
nombres de variables entre llaves dentro de una cadena y anteponiendo una letra f.
El lenguaje también soporta un sistema más antiguo proveniente de C a través del operador
%.
“Unpacking”
Las listas y tuplas soportan un método llamado unpacking (cuya traducción podría ser
“desempaquetamiento”). Veámoslo en un ejemplo:
>>> t = (1, 2, 3)
>>> a, b, c = t
>>> a
1
>>> b
2
>>> c
3
>>> a = t[0]
>>> b = t[1]
>>> c = t[2]
f = open("archivo.txt")
Si no se especifica una ruta, el fichero se busca en el directorio actual. Por defecto el modo
de apertura es únicamente para lectura. La función read() retorna el contenido del archivo
abierto.
print(f.read())
Una vez que se ha terminado de trabajar con el fichero debe cerrarse vía close().
f.close()
f = open("archivo.txt", "w")
f.write("Hola mundo")
Nótese que la función write() reemplaza todo el contenido anterior. Para añadir datos al
final del archivo sin borrar información previa, el fichero debe abrirse en la modalidad
append ("a").
f = open("archivo.txt", "a")
f.write("Hola ")
f.write("mundo")
Para leer, escribir y añadir contenido de un fichero en formato binario, deben utilizarse los
modos "rb", "wb" y "ab", respectivamente.
Apéndice I
El símbolo * (asterisco) también es utilizado para agrupar y desagrupar un conjunto de
objetos. Consideremos una función f con la siguiente definición:
Supongamos entonces que queremos invocar a esta función pero los argumentos los
tenemos en una tupla. Por ejemplo:
args = (1, 2, 3)
f(args[0], args[1], args[2])
Esto es posible cuando conocemos a priori la cantidad de argumentos. Para el resto de los
casos, Python nos permite simplemente hacer:
f(*args)
La expresión *args “desagrupa” los elementos de la tupla y los pasa como argumentos,
dado que f(args) simplemente pasaría una tupla como el primer argumento y restarían
los últimos dos.
Ocurre de forma similar para los argumentos con valores por defecto. Considerando la
siguiente función f:
Podemos definir con anterioridad un diccionario cuyas claves corresponden a los nombres
de los argumentos con nombre y luego “desagruparlo” empleando doble asterisco.
args = (1, 2)
kwargs = {"c": 5, "d": 6}
f(*args, **kwargs)
Cuando en la definición de una función se incluyen asteriscos, indica que Python debe
agrupar los argumentos pasados en una tupla y/o diccionario. Por ejemplo:
De modo que en la llamada f(1, 2, c=3, d=4), args es una tupla (1, 2) y kwargs
un diccionario {"c": 3, "d": 4}.
Nótese que en una definición, *args puede estar precedido por argumentos posicionales.
Por ejemplo, considerando:
Python tiene soporte de primer nivel para el paradigma de orientación a objetos. Las clases
se definen vía la palabra reservada class seguida de su nombre y, entre paréntesis, el
nombre de las clases de las cuales debe heredar, en caso de haber.
class MiClase:
pass
Nótese que la convención de nombramiento difiere de las funciones y otros objetos; en las
clases cada término se escribe con su primera letra en mayúscula y no se emplean guiones
bajos. Recordá que pass no ejecuta ninguna operación sino que simplemente rellena un
lugar que es requerido sintácticamente.
Ahora bien, todas las clases necesitan un punto de entrada: ese código que se ejecutará
cada vez que se haga uso de ella y en donde el programador tendrá la posibilidad de
inicializar lo que sea necesario.
class MiClase:
def __init__(self):
pass
A las funciones definidas dentro de una clase se las conoce con el nombre de método.
Todas las funciones que empiezan y terminan con doble guión bajo son métodos especiales
que utilizará Python y que no están diseñados para ser llamados manualmente (con algunas
excepciones).
mi_objeto = MiClase()
Se dice que mi_objeto es una instancia de la clase MiClase. Para ilustrarlo mejor,
prueba el siguiente código:
class MiClase:
def __init__(self):
print("Has creado una instancia de MiClase.")
mi_objeto = MiClase()
Habrás observado que si bien el método __init__() requiere de un argumento, no
hemos especificado ninguno al crear una instancia. Esto se debe a que Python coloca el
primer argumento de todos los métodos de una clase automáticamente (por convención se
lo llama self). self es una referencia a la instancia actual de la clase.
Por ejemplo, consideremos el siguiente código, el cual crea dos instancias de MiClase.
mi_objeto = MiClase()
otro_objeto = MiClase()
Por lo general estarás utilizando el método __init__() para inicializar objetos dentro de
tu clase. Por ejemplo:
class MiClase:
def __init__(self):
self.a = 1
mi_objeto = MiClase()
print(mi_objeto.a)
mi_objeto = MiClase()
mi_objeto.a += 1
print(mi_objeto.a) # Imprime 2
class MiClase:
def __init__(self, a):
self.a = a
mi_objeto = MiClase(5)
print(mi_objeto.a) # Imprime 5
Una clase también puede incluir funciones, aunque recuerda, siempre el primer argumento
debe ser self.
class MiClase:
def __init__(self, a):
self.a = a
def imprimir_a(self):
print(self.a)
mi_objeto = MiClase(5)
mi_objeto.imprimir_a()
Otros ejemplos:
class MiClase:
def __init__(self, a):
self.a = a
def imprimir_a(self):
print(self.a)
mi_objeto = MiClase(5)
mi_objeto.sumar_e_imprimir(7) # Imprime 12
Herencia
Cuando una clase B hereda de una clase A, aquélla conserva todos los métodos y atributos
de ésta.
class ClaseA:
def __init__(self):
self.a = 1
class ClaseB(ClaseA):
pass
mi_objeto = ClaseB()
print(mi_objeto.a)
class ClaseB(ClaseA):
def __init__(self):
super().__init__()
self.b = 2
class ClaseB(ClaseA):
def __init__(self):
ClaseA.__init__(self)
self.b = 2
Herencia múltiple
Una clase puede heredar de una cantidad arbitraria de clases, indicándolas en la definición
separadas por comas, tal como se haría con los argumentos. Hay que tener en cuenta que
la herencia se resuelve de derecha a izquierda.
class ClaseA:
def __init__(self):
self.a = 1
class ClaseB:
def __init__(self):
self.a = 2
mi_objeto = ClaseC()
print(mi_objeto.a) # Imprime 1
La ClaseC hereda el atributo a de sus clases padres pero, como la resolución ocurre de
derecha a izquierda, el atributo ClaseA.a (1) reemplaza a ClaseB.a (2). Lo mismo ocurre
con los métodos:
class ClaseA:
def __init__(self):
self.a = 1
def mensaje(self):
print("Mensaje de la clase A.")
class ClaseB:
def __init__(self):
self.a = 2
def mensaje(self):
print("Mensaje de la clase B.")
mi_objeto = ClaseC()
mi_objeto.mensaje() # Imprime "Mensaje de la clase A."
Convenciones de encapsulamiento
En Python todos los atributos y métodos de una clase son públicos. No obstante se estila
prefijar un guión bajo a aquellos objetos que se quiera indicar que se tratarán como privados
y no se espera que sean alterados por fuera de la clase. Por ejemplo:
class MiClase:
def __init__(self):
self._atributo_privado = 1
def _funcion_privada(self):
print(self._atributo_privado)