Recordando Python¶
En esta clase repasaremos algunos conceptos de Python que probablemente ya conoces, pero te servirá para familiarizarte con Jupyter Notebook y refrescar la memoria.
Jupyter Notebooks¶
Ojo Piojo
Cada archivo Jupyter Notebook se compone de celdas, que pueden ser Code, Markdown o Raw.
Attention
Los jupyter notebooks poseen dos modos actualmente, de edición y comandos. Dependiendo del modo que se encuentre activo el teclado realiza diferentes cosas.
Modo Edición: Escribes directamente en la celda, de igual manera como si estuvieras en un editor de texto. Se reconoce este modo pues la celda activa posee un borde de color verde (en el theme por defecto).
Modo Comando: Es posible editar acciones al notebook como un todo, no dentro de una celda. Por ejemplo, copiar o crear celdas. Se reconoce este modo pues en una celda hay un borde azul al lado izquierdo.
La documentación oficial de Jupyter Notebook es mucho más formal, pero por lo mismo más extensa, aquí está el link para cuando la necesites.
Algunas otras cosas útiles a saber para trabajar utilizando notebooks:
File: En él, puede crear un nuevo cuaderno o abrir uno preexistente. Aquí es también a donde iría para cambiar el nombre de un Cuaderno. Creo que el elemento de menú más interesante es la opción Guardar y Checkpoint. Esto le permite crear puntos de control a los que puede retroceder si lo necesita.
Edit: Aquí puede cortar, copiar y pegar celdas. Aquí también es donde irías si quisieras eliminar, dividir o fusionar una celda. Puede reordenar celdas aquí también.
View: es útil para alternar la visibilidad del encabezado y la barra de herramientas. También puede activar o desactivar los números de línea dentro de las celdas. Aquí también es donde irías si quieres meterte con la barra de herramientas de la celda.
Insert: es solo para insertar celdas encima o debajo de la celda seleccionada actualmente.
Cell: le permite ejecutar una celda, un grupo de celdas o todas las celdas. También puede ir aquí para cambiar el tipo de celda, aunque personalmente considero que la barra de herramientas es más intuitiva para eso.
Kernel: es para trabajar con el kernel que se ejecuta en segundo plano. Aquí puede reiniciar el kernel, volver a conectarlo, apagarlo o incluso cambiar el kernel que está utilizando su computadora portátil.
Widgets: es para guardar y borrar el estado del widget. Los widgets son básicamente widgets de JavaScript que puede agregar a sus celdas para crear contenido dinámico utilizando Python (u otro Kernel).
Help: es donde debe aprender sobre los atajos de teclado del Notebook, un recorrido por la interfaz de usuario y mucho material de referencia.
Markdown¶
Jupyter Notebook permite que escribamos texto formateado, es decir, texto con cursiva, negritas, títulos de distintos tamaños, etc., de forma simple. Para ello Jupyter nos permite usar Markdown, que es un lenguaje de marcado (markup) muy popular.
Los lenguajes de markup son lenguajes ideados para procesar texto, algunos de los más conocidos son HTML y \(\LaTeX\). Markdown tiene como objetivo ser un lenguaje de sintaxis minimalista, simple de aprender y usar; de esa forma uno puede dar formato al texto pero sin perder demasiado tiempo en los detalles.
La cantidad de tutoriales en la red sobre Markdown es inmenso, por lo que nos centraremos en indicar las opciones que más se utilizan.
Texto en negrita/cursiva: El texto en negrita se indica entre dos pares de asteriscos. De este modo
**palabra**
aparecerá como palabra. Por otro lado, el texto en cursiva se indica entre dos asteriscos simples; es decir*palabra*
aparecerá como palabra.Listas: Las listas en Markdown se realizan indicando un asterisco o un número seguido de un punto si se desean listas numeradas. Markdown organiza automáticamente los items asignándoles el número correcto.
Inclusión de imágenes: La sintaxis para incluir imágenes en Markdown es
![nombre alternativo](dirección de la imagen)
en donde el nombre alternativo aparecerá en caso de que no se pueda cargar la imágen y la dirección puede referirse a una imagen local o un enlace en Internet.Inclusión de código HTML: El lenguaje Markdown es un subconjunto del lenguaje HTML y en donde se necesite un mayor control del formato, se puede incluir directamente el código HTML.
Enlaces: Las celdas de texto pueden contener enlaces, tanto a otras partes del documento, como a páginas en internet u otros archivos locales. Su sintaxis es
[texto](dirección del enlace)
.Fórmulas matemáticas: Gracias al uso de MathJax, se puede incluir código en \(\LaTeX\) para mostrar todo tipo de fórmulas y expresiones matemáticas. Las fórmulas dentro de una línea de texto se escriben entre símbolos de dólar
$...$
, mientras que las expresiones separadas del texto utilizan símbolos de dólar dobles$$...$$
. Los siguientes son ejemplos de fórmulas matemáticas escritas en \(\LaTeX\):
Hola Mundo!¶
Imprimir texto es tan fácil como:
print('Hello World!')
Hello World!
name = 'John Titor'
Cuando escribes texto entre comillas, simples (‘) o dobles (“) la variable pasa a ser de tipo str
(string).
type(name)
str
Guardar variables de string te permite, entre otras cosas, parametrizar mensajes, títulos, loggings, etc.
print("Hola {}!".format(name))
Hola John Titor!
Desde Python 3.6 también puedes hacer uso de los f-strings
print(f"Hola {name}!")
Hola John Titor!
Los strings poseen métodos propios, por ejemplo
name.upper()
'JOHN TITOR'
Tip
En Jupyter Notebook es posible autocompletar métodos y atributos utilizando la tecla TAB, siempre y cuando el objeto ya esté definido.
Tip
Para ver los métodos y atributos de una instancia basta con utilizar dir(variable)
.
Tip
En Jupyter, no siempre es necesario utilizar print en cada celda.
Números y operaciones¶
Un pequeño recuerdo de las operaciones matemáticas más comunes.
1 + 2 # Suma
3
100 - 99 # Resta
1
3 * 4 # Multiplicación
12
42 / 4 # En python 2 la división por defecto es entera
10.5
43 // 4 # División parte entera
10
14 % 4 ## Operación módulo
2
Listas, tuplas, conjuntos y diccionarios¶
Listas, tuplas y conjuntos son colecciones de objetos en Python que poseen ligeras diferencias. Comencemos con las listas que son probablemente las que resultan más naturales.
# Listas
my_list = [1, 2, 3, 4, 5]
print(my_list[0])
1
type(my_list)
list
Puedes acceder a los elementos de tu lista utilizando los corchetes cuadrados []
.
print(my_list[0])
print(my_list[-1])
print(my_list[0:2])
print(my_list[2:])
print(my_list[::2])
print(my_list[:-2])
1
5
[1, 2]
[3, 4, 5]
[1, 3, 5]
[1, 2, 3]
Las tuplas en un comienzo se ven muy parecidas a las listas
my_tuple = (1, 2, 3, 4, 5)
print(my_tuple[4])
5
type(my_tuple)
tuple
Las listas pueden ser modificadas
my_list.append(100)
my_list
[1, 2, 3, 4, 5, 100]
my_list[1] = 42
my_list
[1, 42, 3, 4, 5, 100]
Pero las tuplas no
my_tuple[1] = 42
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-20-2a776f593879> in <module>
----> 1 my_tuple[1] = 42
TypeError: 'tuple' object does not support item assignment
# Las tuplas son objetos inmutables!
try:
my_tuple.append(50)
except Exception as e:
print(e)
'tuple' object has no attribute 'append'
Los conjuntos (sets) son colecciones que no considerar elementos repetidos.
# Conjuntos
my_set = {1, 1, 1, 2, 2, 3}
print(my_set)
{1, 2, 3}
Los conjuntos no tienen orden!
my_set[0]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-23-158c424478a1> in <module>
----> 1 my_set[0]
TypeError: 'set' object is not subscriptable
Finalmente, los diccionarios son conjuntos en los cuales para acceder a sus valores se necesita de una llave.
my_dict = {
'llave': 'corazón',
'sonrisa': 'corazones'
}
print(my_dict['sonrisa'])
corazones
my_dict.values()
dict_values(['corazón', 'corazones'])
my_dict.keys()
dict_keys(['llave', 'sonrisa'])
Otra cosa importante es que tampoco tienen orden! Ni el diccionario, ni sus llaves ni sus valores
my_dict[0]
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-27-2e042f7087f7> in <module>
----> 1 my_dict[0]
KeyError: 0
my_dict.keys()[0]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-28-b08788a06b3c> in <module>
----> 1 my_dict.keys()[0]
TypeError: 'dict_keys' object is not subscriptable
Control Flow¶
Es común que en tus desarrollos quieras controlar ciertas acciones, Python no se queda atrás e implementa los condicionales if
, elif
y else
.
x = 7 # Cambia el valor de x cuando quieras
cota_inferior = 5
cota_superior = 10
if x < cota_inferior:
print('{} es menor que {}'.format(x, cota_inferior))
elif x < cota_superior:
print('{} es mayor igual que {} y menor que {}'.format(x, cota_inferior, cota_superior))
else:
print('{} es mayor igual que {}'.format(x, cota_superior))
7 es mayor igual que 5 y menor que 10
Por otros lados los ciclos son útiles cuando quieres ejecutar una acción varias veces hasta que se cumpla una condición.
# Cilo While
i = 0
while i < 10:
print(f"El cuadrado de {i} es {i ** 2}")
i += 1
El cuadrado de 0 es 0
El cuadrado de 1 es 1
El cuadrado de 2 es 4
El cuadrado de 3 es 9
El cuadrado de 4 es 16
El cuadrado de 5 es 25
El cuadrado de 6 es 36
El cuadrado de 7 es 49
El cuadrado de 8 es 64
El cuadrado de 9 es 81
# Ciclo For
for i in range(1, 10, 2):
if i < 5:
print('{} es menor que 5'.format(i))
else:
print('{} es mayor igual que 5'.format(i))
1 es menor que 5
3 es menor que 5
5 es mayor igual que 5
7 es mayor igual que 5
9 es mayor igual que 5
Warning
Los objetos range no son listas
my_range = range(1, 10, 2)
isinstance(my_range, list) # Puedes validar el tipo de una variable de esta manera
False
type(my_range)
range
range?
my_range.start
1
my_range.start
1
my_range.stop
10
my_range.step
2
Funciones¶
Para definir tu propia función la sintaxis es muy sencilla, por ejemplo, definamos la función que retorna la parte entera de la diferencia absoluta de dos números.
def abs_diff_floor(x, y):
""" Retorna la diferencia entera entre dos valores."""
diff = abs(x - y)
value = int(diff)
return value
abs_diff_floor(20.3, 32.6)
12
O inclusive encapsular cosas que ya hemos hecho con anterioridad, como por ejemplo:
def my_function(x, cota_inferior=5, cota_superior=10):
if x < cota_inferior:
print('{} es menor que {}'.format(x, cota_inferior))
elif x < cota_superior:
print('{} es mayor igual que {} y menor que {}'.format(x, cota_inferior, cota_superior))
else:
print('{} es mayor igual que {}'.format(x, cota_superior))
my_function(5)
5 es mayor igual que 5 y menor que 10
my_function(3, 4, 10)
3 es menor que 4
Librerías¶
Existen librerías de todo tipo para toda clase de tareas en Python, sin embargo, sería poco eficiente que todas estén disponibles por defecto al iniciar un kernel, por lo que el usuario debe manualmente importarlas o incluso instalarlas.
Por ejemplo, ¿Cómo obtener la raíz cuadrada de 49? Fácil, ¿no?
sqrt(49)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-45-d681b475f5f9> in <module>
----> 1 sqrt(49)
NameError: name 'sqrt' is not defined
Wait?! No está implementada?!
Nop! Solo debes importar el módulo de operaciones matemáticas que viene instalado por defecto en Python, ni te imaginas su nombre.
import math # Yep, math...
math?
math.sqrt(49)
7.0
También hay otras fuinciones, por ejemplo floor
math.floor(2.6)
2
En ocasiones te gustaría utilizar tus funciones en otros trabajos, para eso los puedes exportar como archivos .py
e importarlos cuando lo necesites. Por ejemplo, en la misma carpeta que este notebook está el archivo my_packaged_function.py
%ls
M1L01_about_mat281.ipynb M3L04_interactive_visualization.ipynb
M1L02_installation.md M4L01_modeling.ipynb
M1L02_toolkit_and_setup.ipynb M4L02_regression.ipynb
M1L03_python_basics.ipynb M4L03_classification.ipynb
M1L04_git_update.md M4L04_classification_nonparametric.ipynb
M1L04_python_ecosystem.ipynb M4L05_clustering.ipynb
M2L01_scientific_computing.ipynb M4L06_cross_validation.ipynb
M2L02_linear_algebra.ipynb M4L07_model_selection.ipynb
M2L03_data_manipulation.ipynb M4L08_metrics.ipynb
M2L04_data_combining.ipynb M5L01_real_world.ipynb
M2L05_data_aggregation.ipynb lorenz.py
M2L06_eda.ipynb model.py
M3L01_theory_and_landscape.ipynb mpl_heatmap.py
M3L02_imperative_visualization.ipynb my_packaged_function.py
M3L03_declarative_visualization.ipynb
%pycat my_packaged_function.py
import my_packaged_function as mpf # Puedes importar librerías con un alias
Hint
text
Recuerda que en Jupyter puedes explorar la documentación de prácticamente todo con los signos de interrogación ?
. Con ??
te permite ver el código de fuente.
mpf?
mpf??
mpf.pkg_abs_diff_floor?
mpf.pkg_abs_diff_floor??
mpf.pkg_abs_diff_floor(10, 2.3)
7
Hint
Jupyter está basado en IPython, por lo que puedes hacer uso de los comandos mágicos.
# Descomenta y ejecuta esta línea para ver la documentación completa
# %magic
# Lista de comandos mágicos disponibles
%lsmagic
Available line magics:
%alias %alias_magic %autoawait %autocall %automagic %autosave %bookmark %cat %cd %clear %colors %conda %config %connect_info %cp %debug %dhist %dirs %doctest_mode %ed %edit %env %gui %hist %history %killbgscripts %ldir %less %lf %lk %ll %load %load_ext %loadpy %logoff %logon %logstart %logstate %logstop %ls %lsmagic %lx %macro %magic %man %matplotlib %mkdir %more %mv %notebook %page %pastebin %pdb %pdef %pdoc %pfile %pinfo %pinfo2 %pip %popd %pprint %precision %prun %psearch %psource %pushd %pwd %pycat %pylab %qtconsole %quickref %recall %rehashx %reload_ext %rep %rerun %reset %reset_selective %rm %rmdir %run %save %sc %set_env %store %sx %system %tb %time %timeit %unalias %unload_ext %who %who_ls %whos %xdel %xmode
Available cell magics:
%%! %%HTML %%SVG %%bash %%capture %%debug %%file %%html %%javascript %%js %%latex %%markdown %%perl %%prun %%pypy %%python %%python2 %%python3 %%ruby %%script %%sh %%svg %%sx %%system %%time %%timeit %%writefile
Automagic is ON, % prefix IS NOT needed for line magics.
Existen comando mágicos de línea (%
)y de celda completa (%%
)
%timeit comprehension_list = [i*2 for i in range(1000)]
56.7 µs ± 26.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
no_comprehension_list = []
for i in range(1000):
no_comprehension_list.append(i * 2)
103 µs ± 81.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Danger
Ejecutar un timeit es una prueba, no crea tomo tal las variables.
len(comprehension_list)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-62-9fc0a2545cfb> in <module>
----> 1 len(comprehension_list)
NameError: name 'comprehension_list' is not defined