pythonimport sys
print(sys.executable)
🤓 CONTEXTO, CONFIGURACIÓN E INTERACCIÓN 🐍
Este curso es una introducción al trabajo con datos en Python, ofreciendo una visión general de las principales características de las estructuras de datos y librerías incorporadas para la manipulación de datos.
El enfoque principal del curso es el análisis de datos basados en tablas y la preparación de datos para conjuntos pequeños que puedan manejarse en un ordenador personal. Para utilizar estas herramientas, a veces es necesario organizar los datos desordenados en una forma tabular. Python es ideal para esto, y cuanto más familiarizado esté con el lenguaje y sus tipos de datos, más fácil será preparar los conjuntos de datos para su análisis.
⚙️ Configuración Inicial
Rstudio
Usaremos la IDE de Rstudio (claramente no nos limitaremos a ella, usaremos Jupyter Notebook, VSC, Google Colab, etc). Pero más adelante trabajaremos con ambos lenguajes (Python
y R
) simultáneamente por lo cual nos servirá realizar esta configuración.
- Primero necesita conocer con exactitud la ruta del ejecutable
python.exe
💥 que desea usar (sea con Python, conda, venv, etc). Para ello abra la consola de su intérprete (si usa un environment en particular no olvide ingresar a él 📥) y ejecute los comandos mostrados. Guarde dicha dirección en el portapapeles 📎.
- Ahora que conoce la dirección correcta de su intérprete de Python 📇, diríjase a la ruta mostrada en
Rstudio
. 👀 En ocasiones no le saldrá para ser seleccionado, por eso es mejor tener la ruta, péguela en la casilla y espere unos segundos ⌚ que lo reconozca antes de salir y darle guardar o aplicar (si realiza lo anterior de forma muy rápida no le quedará). Le pedirá que reinicie sesión y ya deberá quedar si vuelve a ingresar.
- Por último instalaremos una librería que nos proporcionará un conjunto completo de herramientas para la interoperabilidad entre
Python
yR
🛠️.
"reticulate") install.packages(
Conda
Como usaremos dentro de los .qmd
el parámetro jupyter: python3
, es necesario tener instalada dicha librería en su intérprete 💻, para lo cual ejecute (dentro de su kernel a usar y environment elegido):
conda install jupyter# conda install numpy pandas scikit-learn matplotlib seaborn jupyter
Compruebe que efectivamente haya sido descargado con:
list conda
Quarto
Sí ejecuta el siguiente comando en el terminal ⌨️, deberá obtener algo como lo siguiente:
quarto check jupyter
Como puede observar tenemos un problema ⚠️ y es que no quedó el kernel que elegimos desde un inicio. Y el error mostrado se debe a que obviamente hay módulos que no hemos instalado en dicho intérprete que Quarto
selecciona por defecto. Si desea obtener más información de dicho error consulte: Quarto Uses Wrong Python Version.
Para “corregir” lo anterior debemos apoyarnos de la documentación oficial, la cual indica que se debe crear un archivo _environment
(sí así tal cual sin extensión alguna) y establecer los valores para QUARTO_PYTHON="C:\ProgramData\miniconda3\"
✔️. Así conseguimos que Quarto
pueda establecer y fijar dicha configuración local para nuestro .qmd
.
QUARTO_PYTHON
se establece en: C:\ProgramData\miniconda3\PY_PYTHON
se establece en: C:\ProgramData\miniconda3\RETICULATE_PYTHON
se establece en: C:\ProgramData\miniconda3\
El siguiente blog 📔 explica demasiado bien lo que acabamos de hacer a mayor detalle, para renderizar un documento Quarto
con un entorno específico en RStudio/Posit
.
🟢 Finalmente, cree y ejecute un nuevo .qmd
, puede utilizar la plantilla ejemplo, y agregue el siguiente chunk para que verifique por su propia cuenta que, a pesar de que Quarto a nivel global está usando otro intérprete, al definir el _environment
queda con el que usted especifica.
import sys
print(sys.executable)
print(sys.prefix)
print (sys.version)
C:\ProgramData\miniconda3\pythonw.exe
C:\ProgramData\miniconda3
3.12.2 | packaged by Anaconda, Inc. | (main, Feb 27 2024, 17:28:07) [MSC v.1916 64 bit (AMD64)]
🤖 IPython
🔖 Cualquier comando estándar de shell puede ser utilizado directamente en IPython
anteponiendo el carácter !
. Por ejemplo,
# : ....................... Shell Commands en IPython ........................ :
!ls
Books
LICENSE
Profile.jpg
Python Course.Rproj
_environment
_freeze
_publish.yml
_quarto.yml
_site
about.qmd
files
index.qmd
posts
styles.css
= !pwd
directory print(directory)
['/d/Documentos/JOBS/DNPE/CursoPython']
= "Imprimiendo un texto desde shell"
message !echo {message}
Imprimiendo un texto desde shell
✨ Conceptos Básicos
- 📐 Identación (no llaves {} ): Python utiliza espacios en blanco (tabuladores o espacios) para estructurar el código en lugar de utilizar llaves como en muchos otros lenguajes como
R
yC++
. - 🔣 No se necesita terminar con
;
: El punto y coma puede usarse para separar múltiples sentencias en una sola línea.a = 1; b = 2; c = 3
- 🏷️ Las cadenas admiten tanto comillas simples
'
como comillas dobles"
: Se prefieren las comillas dobles, y para cadenas de varias líneas con saltos de línea, puede utilizar comillas triples"""
. - 🆎 Vinculación (binding): En otros lenguajes, la asignación hará que se copien los datos. En Python, hace que se refieran ahora al mismo objeto,
= [1, 2, 3]
a = a
b 4)
a.append( b
[1, 2, 3, 4]
# Cuando se pasan objetos como argumentos a una función, se crean nuevas variables
# locales que hacen referencia a los objetos originales sin necesidad de copiarlos
def myAppend(lista, elemento):
lista.append(elemento)= [1, 2, 3]
data 4)
myAppend(data, data
[1, 2, 3, 4]
- 💪 Un lenguaje tipado: Cada objeto tiene un tipo (o clase) específico, con la ventaja de que las variables no tienen un tipo inherente asociado a ellas.
= 5 ; print(type(a))
a = "cinco"; print(type(a)) a
<class 'int'>
<class 'str'>
"5" + 5
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[8], line 1 ----> 1 "5" + 5 TypeError: can only concatenate str (not "int") to str
= 4.5
a = 2
b print(a / b)
print(isinstance(a, (int, float)))
2.25
True
Help & Time
# Acceso a la Documentación:
help(len)
Help on built-in function len in module builtins:
len(obj, /)
Return the number of items in a container.
= "a"
letra # letra.<Press Tab>
getattr(letra, "split")
<function str.split(sep=None, maxsplit=-1)>
# Guión bajo '_' para salidas anteriores
1+1
2+2
print(_)
<built-in method split of str object at 0x00007FF807D71CE0>
# Acceder a las entradas anteriores (historial)
%history -n 1-3
1:
import sys
print(sys.executable)
print(sys.prefix)
print (sys.version)
2:
# : ....................... Shell Commands en IPython ........................ :
!ls
3:
directory = !pwd
print(directory)
# : .......................... Timing Code Snippets .......................... :
%timeit sum(range(100)) # IPython Magic Commands
356 ns ± 1.58 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%%timeit # Cuando es más complejo, baja el número de repeticiones
= 0
total for i in range(1000):
for j in range(1000):
+= i * (-1) ** j total
84.9 ms ± 2.39 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Imports
```{python}
# Modulo.py
PI = 3.14159
def cuadrado(x):
return x ** 2
```
import Modulo
print(Modulo.cuadrado(5))
= Modulo.PI
pi # ......................................
from Modulo import PI, cuadrado
cuadrado(PI)# ......................................
import Modulo as m
from Modulo import PI as kte, cuadrado as elevado
= m.cuadrado(kte); print(r1)
r1 = elevado(6) ; print(r2) r2
Operadores Binarios y de Comparación
= [1, 2, 3]
a = a
b = list(a) # Crea una copia
c
print(a is b)
print(a is not c)
True
True
4)
a.append(== c a
False
# Intercambiar los nombres de las variables:
= 1, 2
a, b # tmp = a
# a = b
# b = tmp
= a, b
b, a print(f'a = {a}, b = {b}')
a = 2, b = 1
ℹ️ Tipos Estándar
Tipo | Descripción |
---|---|
None |
El valor “nulo” de Python (solo existe una instancia del objeto None ) |
str |
Tipo de cadena; contiene cadenas Unicode |
bytes |
Datos binarios en bruto |
float |
Número de punto flotante de doble precisión (nota que no hay un tipo double separado) |
bool |
Un valor booleano True o False |
int |
Entero de precisión arbitraria |
Booleans
print(int(False)); print(int(True))
print(True + False)
print(not not not not True)
print(bool(2024.75)) # Todo valor !=0 se convierte en True
print(bool(".")) # Todo valor !="" se convierte en True
0
1
1
True
True
True
Strings
= "Hola mundo \\>"
a print(a)
Hola mundo \>
= """
b Esta cadena es más larga que
abarca varias líneas
"""
print(b)
"\n") b.count(
Esta cadena es más larga que
abarca varias líneas
3
= r"D:\Documentos\Carpeta"
c print(c)
D:\Documentos\Carpeta
# Los strings en Python son inmutables: no se puede modificar una cadena
print(a[5])
5] = "M" a[
m
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[23], line 3 1 # Los strings en Python son inmutables: no se puede modificar una cadena 2 print(a[5]) ----> 3 a[5] = "M" TypeError: 'str' object does not support item assignment
"m", "M") a.replace(
'Hola Mundo \\>'
# Tras esta operación, la variable no se modifica a
'Hola mundo \\>'
list(a) # Las cadenas son una secuencia de caracteres Unicode
['H', 'o', 'l', 'a', ' ', 'm', 'u', 'n', 'd', 'o', ' ', '\\', '>']
Formatted String
Existen varios métodos para formatear cadenas de texto, entre los cuales encontramos:
- Operador de Formato
%
= "Juan"
Nombre = 33
Edad = 3.141592
Pi print("Hola, mi nombre es %s y tengo %d años. Y sé que pi vale: %.2f." % (Nombre, Edad, Pi))
Hola, mi nombre es Juan y tengo 33 años. Y sé que pi vale: 3.14.
- Método
.format()
print("Hola, mi nombre es {} y tengo {} años. Y sé que pi vale: {:.2f}.".format(Nombre, Edad, Pi))
print("Nombre: {name}, Edad: {age}".format(name = "Luis", age = 33))
print("El {0} se encuentra en el {1} y el {1} se encuentra en el {0}.".format("sol", "cielo"))
Hola, mi nombre es Juan y tengo 33 años. Y sé que pi vale: 3.14.
Nombre: Luis, Edad: 33
El sol se encuentra en el cielo y el cielo se encuentra en el sol.
# 0:.3f El 1re valor será un flotantes con 3 decimales
# 1:s El 2do valor será un string
# 2:d El 3re valor será un entero
= "{0:.3f} {1:s} equivalen a US${2:d}"
template format(3.960, "pesos Colombianos", 1) # Intente modificar el tipo de alguno de estos template.
'3.960 pesos Colombianos equivalen a US$1'
- f-strings
= 3.960
Tasa = "Colombianos"
Moneda f"{Tasa:.4f} pesos {Moneda} equivalen a US${Tasa/Tasa}"
'3.9600 pesos Colombianos equivalen a US$1.0'
# Cálculos Dentro:
= 5; b = 10
a print(f"La suma de {a} y {b} es {a + b}. Además, a*b = {a*b}")
La suma de 5 y 10 es 15. Además, a*b = 50
# Alinear Texto:
print(f"{'izquierda':<10} {'centrado':^10} {'derecha':>10}")
izquierda centrado derecha
# Mostrar Números en Diferentes Bases:
= 255
Numero print(f"Decimal: {Numero}, Binario: {Numero:b}, Hexadecimal: {Numero:x}, Octal: {Numero:o}")
Decimal: 255, Binario: 11111111, Hexadecimal: ff, Octal: 377
# Incluir Expresiones y Métodos:
= "Amo Python"
Txt print(f"El texto en mayúsculas es: {Txt.upper()}.")
El texto en mayúsculas es: AMO PYTHON.
# Combinación con Diccionarios:
= {"nombre": "Colombia", "NoPoblacion": 50}
Pais print(f"País: {Pais['nombre']} | Habitantes: {Pais['NoPoblacion']}")
País: Colombia | Habitantes: 50
# Incluir Llaves Literales:
print(f"Este es un valor literal en llaves: {{Numero}}, y este es el valor de la variable: {Numero}.")
Este es un valor literal en llaves: {Numero}, y este es el valor de la variable: 255.
- Método
string.Template
from string import Template
= Template("Hola, mi nombre es $name y tengo $age años.")
template = template.substitute(name = "Juan", age = 33)
mensaje print(mensaje)
Hola, mi nombre es Juan y tengo 33 años.
Método | Sintaxis | Ventajas | Desventajas |
---|---|---|---|
Operador % |
Hola, %s % “mundo” |
Simple y familiar para quienes conocen C | Menos flexible y más propenso a errores |
Método .format() |
Hola, {} .format(“mundo”) |
Muy flexible, soporta nombres y posiciones | Sintaxis más verbosa |
f-strings | f"Hola, {variable}" |
Muy legible, permite expresiones dentro de {} |
Disponible solo en Python 3.6+ |
string.Template |
Template("Hola, $nombre") |
Simple y seguro, fácil de leer | Menos potente para formateo complejo |
None
Abc.
Dates and times
from datetime import datetime, date, time
= datetime(2024, 1, 31, 20, 30, 21)
dt dt.day
31
dt.date()
datetime.date(2024, 1, 31)
dt.time()
datetime.time(20, 30, 21)
"%Y-%m-%d %H:%M") dt.strftime(
'2024-01-31 20:30'
= dt.replace(minute = 0, second = 0)
dt_hour dt_hour
datetime.datetime(2024, 1, 31, 20, 0)
= datetime.now() - dt
delta delta
datetime.timedelta(days=181, seconds=80865, microseconds=14995)
🚩 Objetos Mutables e Inmutables
Tuplas
Una tupla es una secuencia ordenada de objetos de longitud fija e inmutable (una vez asignada no puede modificarse). La forma más sencilla de crear una tupla es con una secuencia de valores separados por comas entre paréntesis.
= (1, 2, 3) # Pueden contener elementos repetidos
tup1 = 4, 5, 6 # Los paréntesis pueden omitirse
tup2 print(tup1); print(tup2)
(1, 2, 3)
(4, 5, 6)
# Se puede convertir cualquier secuencia o iterador
print( tuple([7, 8, 9]) )
print( tuple("Texto") )
(7, 8, 9)
('T', 'e', 'x', 't', 'o')
= (2, 4, 8), (3, 5)
tupCompleja print(tupCompleja)
0] tupCompleja[
((2, 4, 8), (3, 5))
(2, 4, 8)
= tuple(['txt', [1, 2], True])
tupMixta 1].append(3) # Si un objeto dentro de una tupla es mutable, se puede modificar
tupMixta[print(tupMixta)
2] = False tupMixta[
('txt', [1, 2, 3], True)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[47], line 4 2 tupMixta[1].append(3) # Si un objeto dentro de una tupla es mutable, se puede modificar 3 print(tupMixta) ----> 4 tupMixta[2] = False TypeError: 'tuple' object does not support item assignment
print( tup1*2 + (20, 24) + ('year',) )
(1, 2, 3, 1, 2, 3, 20, 24, 'year')
# Desempaquetado (unpacking)
= tup1
uno, dos, tres print(uno)
= tupCompleja
(a, b, c), (d, e) print(a)
1
2
= [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
seq for a, b, c in seq:
print(f'a = {a}, b = {b}, c = {c}')
a = 1, b = 2, c = 3
a = 4, b = 5, c = 6
a = 7, b = 8, c = 9
*rest = (1, 2, 3, 4, 5)
first, second, print(f"{first} || {second} || {rest}")
# El guión bajo (_) para descartar las variables no deseadas
*_ = (1, 2, 3, 4, 5)
first, second, print(*_)
1 || 2 || [3, 4, 5]
3 4 5
# Si desea definir una tupla con un solo elemento debe incluir una coma al final:
= (3,)
my_t print(my_t)
# Métodos
1, 0, 1, 1, 0).count(0) (
(3,)
2
Listas
Una lista es una colección de elementos en un orden determinado. Puedes poner lo que quieras en una lista, y los elementos que la componen no tienen porqué estar relacionados de ninguna manera en particular. En Python, los corchetes [ ]
indican una lista, y los elementos individuales de la lista están separados por comas.
- Las posiciones de índice empiezan en 0, no en 1.
- Las listas son de longitud variable y su contenido puede modificarse (son mutables).
= [0, "honda", "yamaha", "suzuki", None]
motorcycles print(motorcycles)
list(tup1)
[0, 'honda', 'yamaha', 'suzuki', None]
[1, 2, 3]
# Añadir y eliminar elementos
"ducati")
motorcycles.append(1, "1")
motorcycles.insert(del motorcycles[-2] # Removing an Item Using the del Statement
0) # Popping Items from Any Position
motorcycles.pop(print(motorcycles)
['1', 'honda', 'yamaha', 'suzuki', 'ducati']
La inserción (insert
) es más costosa computacionalmente que la adición (append
), ya que las referencias a los elementos subsiguientes deben desplazarse internamente para dejar espacio al nuevo elemento.
"2"); print(motorcycles)
motorcycles.append("2"); print(motorcycles) # Removing an Item by Value motorcycles.remove(
['1', 'honda', 'yamaha', 'suzuki', 'ducati', '2']
['1', 'honda', 'yamaha', 'suzuki', 'ducati']
# Sorting a List
; print(motorcycles)
motorcycles.sort()= True); print(motorcycles)
motorcycles.sort(reverse print(sorted(motorcycles)); print(motorcycles)
['1', 'ducati', 'honda', 'suzuki', 'yamaha']
['yamaha', 'suzuki', 'honda', 'ducati', '1']
['1', 'ducati', 'honda', 'suzuki', 'yamaha']
['yamaha', 'suzuki', 'honda', 'ducati', '1']
print(motorcycles.reverse())
len(motorcycles)
None
5
# Python returns another index error
= []
listA print(listA[-1])
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) Cell In[58], line 3 1 # Python returns another index error 2 listA = [] ----> 3 print(listA[-1]) IndexError: list index out of range
= []
squares for value in range(1, 11):
** 2)
squares.append(value print(squares)
# List Comprehensions
= [value**2 for value in range(1, 11)]
squares print(squares)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# Slicing a List
print(motorcycles[0:3])
print(motorcycles[2:])
print(motorcycles[-2:])
['1', 'ducati', 'honda']
['honda', 'suzuki', 'yamaha']
['suzuki', 'yamaha']
# Copying a List
= ["pizza", "arepa", "empanada"]
onces = onces[:]
tusOnces "buñuelo")
onces.append("pan")
tusOnces.append(print(onces); print(tusOnces)
['pizza', 'arepa', 'empanada', 'buñuelo']
['pizza', 'arepa', 'empanada', 'pan']
Diccionarios
Un diccionario (conocido en otros lenguajes como maps
o associative arrays
) almacena una colección de pares clave-valor
, donde clave
y valor
son objetos Python. Cada clave está asociada a un valor, de modo que un valor puede ser convenientemente recuperado, insertado, modificado o eliminado dada una clave en particular. Tenga presente que las claves únicas (no permiten duplicados en las claves).
= {'color': 'blanco', 'altura': 1.79}
fisico "ojos"] = "azules"
fisico["peso"] = 87
fisico[print(fisico)
{'color': 'blanco', 'altura': 1.79, 'ojos': 'azules', 'peso': 87}
# Diccionario con tuplas como claves
= {
puntos 0, 0): "Origen",
(1, 2): "Punto A",
(3, 4): "Punto B"
(
}print(puntos[(1, 2)])
Punto A
Conjuntos
Abc.
# Mutable
= [1, 2, 3]
mi_lista print(id(mi_lista)) # Ejemplo de ID: 2180570982400
4)
mi_lista.append(print(id(mi_lista)) # Mismo ID: 2180570982400
# Inmutable
= (1, 2, 3)
mi_tupla print(id(mi_tupla)) # Ejemplo de ID: 2180571003840
= (1, 2, 3, 4)
mi_tupla print(id(mi_tupla)) # Nuevo ID: 2180571086992
1610394567040
1610394567040
1610394610496
1610394566256
➿ Flujo de Control
if
, elif
, and else
= 5; x = 4; y = 3; z = 2
w if x < 0:
print("x es negativo.")
elif x == 0:
print("x es cero")
elif w > x > y > z:
print("Los valores están en orden.")
else:
print("Otro caso diferente.")
Los valores están en orden.
for
= [1, 2, None, 4, None, 5] # sum(numeros)
numeros = 0
total for value in numeros:
if value is None:
continue
if value == 4:
break # La sentencia 'break' se usa para salir del bucle
+= value
total total
3
# 'break' sólo termina el for más interno, cualquier for externo continuará
for i in range(4):
for j in range(4):
if j > i:
break
print((i, j))
(0, 0)
(1, 0)
(1, 1)
(2, 0)
(2, 1)
(2, 2)
(3, 0)
(3, 1)
(3, 2)
(3, 3)
while
Esta estructura permite ejecutar repetidamente un bloque de código mientras una condición especificada se evalúa como verdadera. Este ciclo es útil cuando no se sabe de antemano cuántas veces se necesitará repetir el bloque de código, a diferencia del ciclo for
, que itera sobre una secuencia de elementos de longitud conocida.
while True:
= input("Escribe 'salir' para terminar: ")
entrada if entrada.lower() == "salir":
break
pass
Es la sentencia no-op
(o no hacer nada
) de Python. Puede usarse en bloques en los que no se va a realizar ninguna acción. Sólo es necesaria porque Python utiliza espacios en blanco para delimitar los bloques.
Cuando la ejecución del programa alcanza una sentencia continue
, la ejecución del programa salta inmediatamente al inicio del bucle y reevalúa la condición del bucle.
while True:
print('¿Quién eres tú?')
= input()
name if name != 'Juan':
continue
print('Hola Juan, cuál es tu contraseña (es un equipo)')
= input()
password if password == 'nacional':
break
print('Acceso Concedido.')
- Pass (
for
,if
): No realiza ninguna acción y se utiliza como marcador de lugar (placeholder para futura implementación).- Continue (
for
,while
): Salta a la siguiente iteración del bucle, omitiendo el resto del código en la iteración actual.- Break (
if
): Termina el bucle inmediatamente, saliendo de la estructura de control de flujo.
range
print(f"{ range(10) }")
print(f"{ range(1, 10) }")
print(f"{ list(range(0, 20, 2)) }")
print(f"{ list(range(5, -1, -1)) }")
range(0, 10)
range(1, 10)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[5, 4, 3, 2, 1, 0]
➿ Funciones
Las funciones en Python son bloques de código reutilizables que permiten estructurar y organizar mejor los programas. Se definen usando la palabra clave def
y pueden aceptar argumentos y devolver valores.
# Py añade return None al final de cualquier definición de función sin sentencia return:
def Saludo(nombre):
print("Hola " + nombre)
= Saludo("Carlos")
spam None == spam
Hola Carlos
True
En un programa de Python, hay exactamente un único ámbito global. Este ámbito global es el contexto en el que las variables globales se definen y existen a lo largo de la ejecución del programa.
- En cuanto a los ámbitos locales, el número de estos puede variar. Cada vez que se define y se llama a una función, se crea un nuevo ámbito local. Por lo tanto, el número de ámbitos locales depende del número de funciones (incluidas las funciones anidadas) y métodos que se llaman durante la ejecución del programa.
# Las variables locales no pueden utilizarse en el ámbito global:
def getPI():
= 3.1415
PI
getPI()print(PI)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[70], line 5 3 PI = 3.1415 4 getPI() ----> 5 print(PI) NameError: name 'PI' is not defined
# Los ámbitos locales no pueden utilizar variables de otros ámbitos locales:
def a():
= 444
phone
b()print(phone)
def b():
= 555
phone a()
444
# Las variables globales pueden leerse desde un ámbito local:
def a():
print(cte)
= 1234
cte
a()print(cte)
1234
1234
# Si necesitas modificar una variable global desde dentro de una función:
def a():
global cte
= 'Ahora soy una Variable Global'
cte
= 'Global'
cte
a()print(cte)
Ahora soy una Variable Global
# Funciones con Valores por Defecto:
def saludar(nombre = "Paola"):
print(f"¡Hola, {nombre}!")
saludar()"Pedro") saludar(
¡Hola, Paola!
¡Hola, Pedro!
# Funciones con Varios Valores de Retorno:
def operaciones(a, b):
= a + b
suma = a - b
resta return suma, resta
= operaciones(10, 2)
suma, resta print(f"Suma: {suma}\t| Resta: {resta}")
Suma: 12 | Resta: 8
# Evitar que un programa se bloquee cuando recibe un error:
def a(b):
try:
return 1/b
except ZeroDivisionError:
print('Error: b debe ser diferente de 0.')
print(a(2))
print(a(0))
0.5
Error: b debe ser diferente de 0.
None
*args
El parámetro args se usa en las funciones para pasar un número variable de argumentos posicionales. Dentro de la función, args
es una tupla que contiene todos los argumentos posicionales proporcionados.
Características:
- Permite pasar una cantidad variable de argumentos a una función.
- Los argumentos se agrupan en una tupla dentro de la función.
def imprimir_argumentos(*args):
for i, arg in enumerate(args):
print(f"Argumento {i}: {arg}")
'a', 'b', 'c') imprimir_argumentos(
Argumento 0: a
Argumento 1: b
Argumento 2: c
**kwargs
El parámetro kwargs se usa para pasar un número variable de argumentos con nombre (palabra clave). Dentro de la función, kwargs
es un diccionario que contiene todos los argumentos con nombre proporcionados.
Características:
- Permite pasar una cantidad variable de argumentos con nombre a una función.
- Los argumentos se agrupan en un diccionario dentro de la función.
def mostrar_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
= "Alice", edad = 30, ciudad = "Nueva York") mostrar_info(nombre
nombre: Alice
edad: 30
ciudad: Nueva York
# Ejemplo combinado:
def combinar(*args, **kwargs):
print("Argumentos posicionales:", args)
print("Argumentos con nombre:", kwargs)
1, 2, 3, a = "Uno", b = "Dos", c = "Tres") combinar(
Argumentos posicionales: (1, 2, 3)
Argumentos con nombre: {'a': 'Uno', 'b': 'Dos', 'c': 'Tres'}
Funciones Lambda
Son funciones anónimas y de una sola línea que pueden ser definidas usando la palabra clave lambda argumentos: expresión
. Son especialmente útiles cuando se necesita una función pequeña y desechable que se puede definir en una expresión.
= lambda x: x ** 2
cuadrado print(cuadrado(5))
= lambda x, y: x * y
multiplicar print(multiplicar(4, 6))
25
24
Uso con Funciones Integradas
Las funciones lambda son especialmente útiles cuando se combinan con ciertas funciones integradas de Python.
map()
: Aplica una función a cada ítem de un iterable (como una lista) y devuelve un nuevo iterable con los resultados.
= list(range(11))
numeros = map(lambda x: x**2, numeros)
cuadrados print(list(cuadrados))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
filter()
: Filtra un iterable, permitiendo sólo los ítems que coincidan con una condición.
= filter(lambda x: x%2 == 0, numeros)
pares print(list(pares))
[0, 2, 4, 6, 8, 10]
print(list(filter(lambda x: (x % 2 == 0) and (x > 7), numeros)))
[8, 10]
reduce()
: Aplica una función a los ítems de un iterable, acumulando el resultado.
from functools import reduce
= reduce(lambda x,y: x + y, numeros)
suma_total print(suma_total)
55
sorted()
: Las funciones lambda pueden ser usadas para personalizar el ordenamiento de listas.
= [(1, 2), (3, 4), (5, 1), (7, 3)]
coordenadas = sorted(coordenadas, key = lambda x: x[1])
ordenado print(ordenado)
[(5, 1), (1, 2), (7, 3), (3, 4)]
= [
Notas 'Nombre': 'Ana', 'Definitiva': 8},
{'Nombre': 'Juan', 'Definitiva': 6},
{'Nombre': 'Maria', 'Definitiva': 9}
{
]print(sorted(Notas, key = lambda x: x['Definitiva']))
[{'Nombre': 'Juan', 'Definitiva': 6}, {'Nombre': 'Ana', 'Definitiva': 8}, {'Nombre': 'Maria', 'Definitiva': 9}]
Limitaciones
- Una sola expresión: Las lambdas están limitadas a una única expresión. No pueden contener declaraciones ni múltiples líneas de código.
- Legibilidad: Aunque útiles para funciones cortas y simples, las lambdas pueden hacer el código más difícil de leer si se usan en exceso o de manera compleja.
Decoradores
Los decoradores en Python son una herramienta poderosa que permite modificar el comportamiento de una función o método. Los decoradores permiten envolver una función en otra función, lo que facilita añadir funcionalidades adicionales de una manera muy elegante y reutilizable.
def decorador(func):
def envoltura():
print("Antes de la función")
func()print("Después de la función")
return envoltura
@decorador
def f():
print("Función original")
f()
Antes de la función
Función original
Después de la función
# Registro de Llamadas a Funciones:
def registrar(func):
def envoltura(*args, **kwargs):
print(f"Llamando a {func.__name__} con {args} y {kwargs}")
= func(*args, **kwargs)
resultado print(f"{func.__name__} retornó {resultado}")
return resultado
return envoltura
@registrar
def suma(a, b):
return a + b
3, 5) suma(
Llamando a suma con (3, 5) y {}
suma retornó 8
8
# Contador de Llamadas a una Función:
def contador_de_llamadas(func):
def wrapper(*args, **kwargs):
+= 1
wrapper.llamadas print(f"Llamada número: {wrapper.llamadas}")
return func(*args, **kwargs)
= 0
wrapper.llamadas return wrapper
@contador_de_llamadas
def mi_funcion():
print("Ejecutando la función")
mi_funcion() mi_funcion()
Llamada número: 1
Ejecutando la función
Llamada número: 2
Ejecutando la función
# Medición de Tiempo de Ejecución:
import time
def medir_tiempo(func):
def envoltura(*args, **kwargs):
= time.time()
inicio = func(*args, **kwargs)
resultado = time.time()
fin print(f"{func.__name__} tomó {fin - inicio} segundos")
return resultado
return envoltura
@medir_tiempo
def contar_hasta(numero):
for i in range(numero):
pass
return numero
1000000) contar_hasta(
contar_hasta tomó 0.018638134002685547 segundos
1000000
# Memorización de Resultados:
def memoize(func):
= {}
cache def envoltura(*args):
if args in cache:
return cache[args]
= func(*args)
resultado = resultado
cache[args] return resultado
return envoltura
@memoize
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(30))
832040
# Decoradores con Parámetros:
def repetir(veces):
def decorador(func):
def envoltura(*args, **kwargs):
for _ in range(veces):
*args, **kwargs)
func(return envoltura
return decorador
@repetir(3)
def saludar():
print("¡Hola!")
saludar()
¡Hola!
¡Hola!
¡Hola!
Documentación de funciones
En Python, la documentación de funciones se suele escribir utilizando docstrings, que son cadenas de texto que describen el propósito y el uso de una función, método, clase o módulo.
def nombre_funcion(param1, param2):
"""
Descripción breve de lo que hace la función.
Args:
param1 (tipo): Descripción de param1.
param2 (tipo): Descripción de param2.
Returns:
tipo: Descripción de lo que devuelve la función.
Raises:
ExceptionType: Descripción de las excepciones que puede lanzar la función.
"""
pass
def division(a, b):
"""
Divide a entre b.
Args:
a (float): El numerador.
b (float): El denominador.
Returns:
float: El resultado de la división.
Examples:
>>> division(1, 2)
0.5
>>> division(1, 10)
0.1
Raises:
ValueError: Si b es cero.
"""
if b == 0:
raise ValueError("El denominador no puede ser cero.")
return a / b
help(division)
1, 0) division(
Help on function division in module __main__:
division(a, b)
Divide a entre b.
Args:
a (float): El numerador.
b (float): El denominador.
Returns:
float: El resultado de la división.
Examples:
>>> division(1, 2)
0.5
>>> division(1, 10)
0.1
Raises:
ValueError: Si b es cero.
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[93], line 27 24 return a / b 26 help(division) ---> 27 division(1, 0) Cell In[93], line 23, in division(a, b) 2 """ 3 Divide a entre b. 4 (...) 20 21 """ 22 if b == 0: ---> 23 raise ValueError("El denominador no puede ser cero.") 24 return a / b ValueError: El denominador no puede ser cero.
Convenciones de Formato
Hay varias convenciones para escribir docstrings. La más común en Python es la convención de estilo Google, pero también existen otras como el estilo NumPy/SciPy y el estilo reStructuredText (reST), que es utilizado por Sphinx para generar documentación.
Estilo Google
def f(param1, param2):
"""
Una breve descripción de la función.
Args:
param1 (int): El primer parámetro.
param2 (str): El segundo parámetro.
Returns:
bool: El valor de retorno.
"""
pass
Estilo NumPy/SciPy
def f(param1, param2):
"""
Una breve descripción de la función.
Parameters
----------
param1 : int
El primer parámetro.
param2 : str
El segundo parámetro.
Returns
-------
bool
El valor de retorno.
"""
pass
Estilo reStructuredText (reST)
def f(param1, param2):
"""
Una breve descripción de la función.
:param param1: El primer parámetro.
:type param1: int
:param param2: El segundo parámetro.
:type param2: str
:returns: El valor de retorno.
:rtype: bool
"""
pass
Variables Especiales y Útiles
name
En Python, name es una variable especial que se define automáticamente. Su valor depende de cómo se ejecuta el archivo:
- Si el archivo se ejecuta directamente, name es igual a “main”.
- Si el archivo se importa como un módulo en otro archivo, name toma el nombre del archivo (sin la extensión
.py
).
¿Por qué usar if name == "main"
:?
El uso de esta construcción permite definir una sección de código que solo se ejecutará cuando el archivo se ejecute directamente, y no cuando se importe como módulo. Esto es útil para escribir scripts que pueden funcionar tanto como programas independientes como módulos reutilizables.
# mi_script.py
def saludo():
print("¡Hola, Mundo!")
if __name__ == "__main__":
saludo()# Si ejecutas mi_script.py directamente, la salida será ¡Hola, Mundo!.
# Si importas mi_script.py en otro archivo, no se ejecutará automáticamente saludo().
¡Hola, Mundo!
sys.argv
El módulo sys
proporciona acceso a algunos objetos utilizados o mantenidos por el intérprete de Python y a funciones que interaccionan fuertemente con el intérprete.
import sys
# Lista en la que cada elemento es un argumento pasado al script
def main():
print("Nombre del script:", sys.argv[0])
for i, arg in enumerate(sys.argv[1:], start = 1):
print(f"Argumento {i}: {arg}")
if __name__ == "__main__":
main()
Nombre del script: C:\Users\Jason\AppData\Roaming\Python\Python312\site-packages\ipykernel_launcher.py
Argumento 1: -f
Argumento 2: C:\Users\Jason\AppData\Local\Temp\tmp9upt3ui7.json
Argumento 3: --HistoryManager.hist_file=:memory:
os.environ
El módulo os
permite interactuar con el sistema operativo.
import os
# Diccionario que contiene las variables de entorno del sistema
def mostrar_variables_entorno():
for clave, valor in os.environ.items():
print(f"{clave}: {valor}")
if __name__ == "__main__":
mostrar_variables_entorno()
ALLUSERSPROFILE: C:\ProgramData
APPDATA: C:\Users\Jason\AppData\Roaming
CLICOLOR_FORCE: 1
COMMONPROGRAMFILES: C:\Program Files\Common Files
COMMONPROGRAMFILES(X86): C:\Program Files (x86)\Common Files
COMMONPROGRAMW6432: C:\Program Files\Common Files
COMPUTERNAME: JEISONALARCON
COMSPEC: C:\Windows\system32\cmd.exe
CURL_CA_BUNDLE: C:/PROGRA~1/R/R-44~1.0PA/etc/curl-ca-bundle.crt
DENO_DOM_PLUGIN: C:\PROGRA~1\Quarto\bin\tools\x86_64\deno_dom\plugin.dll
DENO_NO_UPDATE_CHECK: 1
DENO_TLS_CA_STORE: system,mozilla
DISPLAY: :0
DRIVERDATA: C:\Windows\System32\Drivers\DriverData
EFC_5056: 1
GFORTRAN_STDERR_UNIT: -1
GFORTRAN_STDOUT_UNIT: -1
GIT_ASKPASS: rpostback-askpass
HOME: C:\Users\Jason\OneDrive\Documents
HOMEDRIVE: C:
HOMEPATH: \Users\Jason
IPY_INTERRUPT_EVENT: 1116
JPY_INTERRUPT_EVENT: 1116
JPY_PARENT_PID: 852
LOCALAPPDATA: C:\Users\Jason\AppData\Local
LOGONSERVER: \\JEISONALARCON
MPLBACKEND: module://matplotlib_inline.backend_inline
MPLENGINE: tkAgg
MSYS2_ENV_CONV_EXCL: R_ARCH
NO_COLOR: TRUE
NUMBER_OF_PROCESSORS: 16
ONEDRIVE: C:\Users\Jason\OneDrive
ORIGINAL_XDG_CURRENT_DESKTOP: undefined
OS: Windows_NT
PATH: C:\rtools44\x86_64-w64-mingw32.static.posix\bin;C:\rtools44\usr\bin;C:\Program Files\R\R-4.4.0patched\bin\x64;C:\Program Files\Quarto\bin;C:\Program Files\Python312\Scripts\;C:\Program Files\Python312\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Users\Jason\AppData\Local\Microsoft\WindowsApps;C:\Users\Jason\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\Jason\AppData\Local\Programs\MiKTeX\miktex\bin\x64\;C:\Program Files\Quarto\bin;C:\Program Files\RStudio\resources\app\bin\postback
PATHEXT: .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW
PROCESSOR_ARCHITECTURE: AMD64
PROCESSOR_IDENTIFIER: AMD64 Family 25 Model 116 Stepping 1, AuthenticAMD
PROCESSOR_LEVEL: 25
PROCESSOR_REVISION: 7401
PROGRAMDATA: C:\ProgramData
PROGRAMFILES: C:\Program Files
PROGRAMFILES(X86): C:\Program Files (x86)
PROGRAMW6432: C:\Program Files
PSMODULEPATH: C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules
PUBLIC: C:\Users\Public
PYDEVD_DISABLE_FILE_VALIDATION: 1
PYTHONIOENCODING: utf-8
PY_PYTHON: C:\ProgramData\miniconda3\
QUARTO_BIN_PATH: C:\PROGRA~1\Quarto\bin
QUARTO_DENO: C:\PROGRA~1\Quarto\bin\tools\x86_64\deno
QUARTO_DOCUMENT_PATH: D:\Documentos\JOBS\DNPE\CursoPython\posts\Getting Started
QUARTO_FIG_DPI: 192
QUARTO_FIG_FORMAT: png
QUARTO_FIG_HEIGHT: 5
QUARTO_FIG_WIDTH: 7
QUARTO_PROFILE:
QUARTO_PROJECT_ROOT: D:\Documentos\JOBS\DNPE\CursoPython
QUARTO_PYTHON: C:\ProgramData\miniconda3\
QUARTO_RENDER_TOKEN: f20dd7d5-943c-414a-9790-0d782f256425
QUARTO_SHARE_PATH: C:\PROGRA~1\Quarto\share
RETICULATE_PYTHON: C:\ProgramData\miniconda3\
RMARKDOWN_MATHJAX_PATH: C:/Program Files/RStudio/resources/app/resources/mathjax-27
RSTUDIO: 1
RSTUDIO_CHILD_PROCESS_PANE: job
RSTUDIO_CLI_HYPERLINKS: true
RSTUDIO_CONSOLE_COLOR: 256
RSTUDIO_CONSOLE_WIDTH: 193
RSTUDIO_DESKTOP_EXE: C:\Program Files\RStudio\rstudio.exe
RSTUDIO_MSYS_SSH: C:/Program Files/RStudio/resources/app/bin/msys-ssh-1000-18
RSTUDIO_PANDOC: C:/Program Files/RStudio/resources/app/bin/quarto/bin/tools
RSTUDIO_PROGRAM_MODE: desktop
RSTUDIO_SESSION_PID: 9388
RSTUDIO_SESSION_PORT: 37453
RSTUDIO_USER_IDENTITY: Jason
RSTUDIO_WINUTILS: C:/Program Files/RStudio/resources/app/bin/winutils
RS_LOCAL_PEER: \\.\pipe\37453-rsession
RS_LOG_LEVEL: WARN
RS_RPOSTBACK_PATH: C:/Program Files/RStudio/resources/app/bin/rpostback.exe
RS_SHARED_SECRET: 3a833e1a-f1b9-434a-8e77-092fec2a585e
RTOOLS44_HOME: C:\rtools44
R_ARCH: /x64
R_CLI_HAS_HYPERLINK_IDE_HELP: true
R_CLI_HAS_HYPERLINK_IDE_RUN: true
R_CLI_HAS_HYPERLINK_IDE_VIGNETTE: true
R_COMPILED_BY: gcc 13.2.0
R_DOC_DIR: C:/PROGRA~1/R/R-44~1.0PA/doc
R_HOME: C:/PROGRA~1/R/R-44~1.0PA
R_INCLUDE_DIR: C:/PROGRA~1/R/R-44~1.0PA/include
R_LIBS_SITE: C:/PROGRA~1/R/R-44~1.0PA/site-library
R_LIBS_USER: C:\Users\Jason\AppData\Local/R/win-library/4.4
R_PLATFORM:
R_RTOOLS44_PATH: C:\rtools44/x86_64-w64-mingw32.static.posix/bin;C:\rtools44/usr/bin
R_RUNTIME: ucrt
R_SHARE_DIR: C:/PROGRA~1/R/R-44~1.0PA/share
R_USER: C:/Users/Jason/OneDrive/Documents
SESSIONNAME: Console
SSH_ASKPASS: rpostback-askpass
SYSTEMDRIVE: C:
SYSTEMROOT: C:\Windows
TEMP: C:\Users\Jason\AppData\Local\Temp
TERM: xterm-color
TMP: C:\Users\Jason\AppData\Local\Temp
USERDOMAIN: JEISONALARCON
USERDOMAIN_ROAMINGPROFILE: JEISONALARCON
USERNAME: Jason
USERPROFILE: C:\Users\Jason
WINDIR: C:\Windows
PYDEVD_USE_FRAME_EVAL: NO
CLICOLOR: 1
FORCE_COLOR: 1
PAGER: cat
GIT_PAGER: cat
Python
VS. R
= "Hola, Mundo!"
cadena # Convertir a minúsculas
print(cadena.lower()) # tolower(cadena)
# Reemplazar caracteres
print(cadena.replace("Mundo", "Python")) # sub("Mundo", "R", cadena)
# Dividir cadenas
print(cadena.split(", ")) # strsplit(cadena, ", ")
# Comprensiones de Listas
print([x ** 2 for x in range(10)]) # sapply(0:9, function(x) x^2)
Funciones Anidadas y Clausuras
def exterior(x):
def interior(y):
return x + y
return interior
print(exterior(5))
#| eval: false
exterior <- function(x) {
interior <- function(y) {
x + y
}
interior
}
exterior(5)
Creación de Factores
= ["M", "F", "F", "M", "M"]
sexo = {"M": "Male", "F": "Female"}
niveles print([niveles[s] for s in sexo])
#| eval: false
sexo <- factor(c("M", "F", "F", "M", "M"))
levels(sexo) <- c("Female", "Male")
print(sexo)
Programación Orientada a Objetos (OOP)
class Coche:
def __init__(self, marca, modelo):
self.marca = marca
self.modelo = modelo
def descripcion(self):
return f"Coche: {self.marca} {self.modelo}"
= Coche("Toyota", "Corolla")
mi_coche print(mi_coche.descripcion()) # Coche: Toyota Corolla
#| eval: false
setClass("Coche",
slots = list(marca = "character", modelo = "character"))
setMethod("initialize", "Coche",
function(.Object, marca, modelo) {
.Object@marca <- marca
.Object@modelo <- modelo
.Object
})
setMethod("descripcion", "Coche",
function(object) {
paste("Coche:", object@marca, object@modelo)
})
mi_coche <- new("Coche", marca = "Toyota", modelo = "Corolla")
descripcion(mi_coche) # "Coche: Toyota Corolla"
Python Enhancement Proposal (PEP): https://peps.python.org/pep-0008/
https://docs.python.org/es/3/library/trace.html python -m trace –count -C . somefile.py Esto ejecutará somefile.py y generará listados anotados de todos los módulos de Python importados durante la ejecución en el directorio actual.
https://jjallaire.github.io/pydata-quarto-dashboards/#/learning-more
# import numpy as np
# import matplotlib.pyplot as plt
# import pandas as pd
# import seaborn as sns
# import statsmodels as sm
#
# pd.options.display.max_columns = 20
# pd.options.display.max_rows = 20
# pd.options.display.max_colwidth = 80
# np.set_printoptions(precision = 4, suppress = True)