Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Eduardo Zepeda
2022-07-19
Contents
help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
dir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Invierte un array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Enumerate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Dequeue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
NamedTuple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
timeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Cprofile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Dataclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Desestructuración de iterables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1
Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Diccionarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
__name__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
’__main__’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Como ya sabes, Python es un lenguaje bastante simple de aprender, esta simplicidad abstrae muchísi-
mas funcionalidades y nos permite realizar casi todo de una manera directa. Sin embargo hay una serie
de funciones o características que, por la simplicidad del lenguaje, pasan inadvertidas para numerosos
desarrolladores. Estos trucos son características del lenguaje o librerías menos populares, pero no por
A veces cuando tenemos duda de como funciona algun objeto o función interna de Python vamos di-
recto a google y buscamos el problema, casi siempre esto nos dirige a la documentación oficial o algún
blog bien optimizado. ¿Y si te digo que podrías haber obtenido la misma información sin abandonar la
help
La función help tomará un objeto como argumento y te imprimirá en pantalla el texto de ayuda, toda
la información que necesitas saber sobre un objeto con su descripción, funciones y la ubicación en el
2
help(<objeto>)
Ejemplo:
import math
help(math)
# NAME
# math
# MODULE REFERENCE
# https://docs.python.org/3.9/library/math
dir
La función dir tomará un objeto como argumento y te imprimirá en pantalla los métodos del objeto y
sus atributos. Es bastante útil para saber con que métodos y atributos contamos en un objeto.
dir(<objeto>)
Ejemplo:
import math
dir(math)
¿Sabías que Python tiene algo parecido a un operador ternario? Sí, como el de javascript y otros lengua-
jes, para llevar a cabo flujos de tipo if…else en una sola linea.
Por ejemplo:
numero = 2
3
Trabajando con secuencias
Invierte un array
<arr>[::-1]
Ejemplo:
arr = [1,2,3]
print(arr[::-1])
# [3,2,1]
¿Por qué superficial? Porque no crea dos objetos distintos, sino que guarda una referencia al mismo
objeto.
<secuencia>[:]
Ejemplo:
copyArr = arr[:]
arr[0] is copyArr[0]
True
print(copyArr)
Para crear una copia profunda, en la que se cree otro objeto se usa la función deepcopy.
import copy
arrCopy = copy.deepcopy(arr)
4
Otra manera de hacerlo es desestructurando un array, te explico como más adelante.
Zip
Zip permite unir cualquier número iterables en una lista de tuplas. Zip (cierre en inglés) funciona exac-
tamente igual que un cierre de ropa, en el que un diente de un lado se une a un diente del otro.
zip(*iterables)
Dado que devuelve un objeto zip, es necesario combinarlo con list para obtener una representación
más amigable.
Ejemplo:
zip([1,2,3], ["Uno","Dos","Tres"])
list(zip([1,2,3], ["Uno","Dos","Tres"]))
Enumerate
Enumerate toma un iterable y le asigna un índice, combina muy bien cuando lo combina usando ciclos
for.
enumerate(<iterable>, start=0)
Ejemplo:
print(index, emoji)
# 0 sol
# 1 nube
# 2 estrella
5
Counter
La librería collections cuenta con múltiples funciones útiles, entre ellas Counter, que se encarga de
Counter(<iterable>=None, /, **kwds)
Ejemplo:
Counter(array)
Dequeue
Dequeu es una cola doble que soporta la adición o eliminación de ambos extremos en un tiempo de
O(1).
En contraste, las listas normales incurren en O(n) cuando se inserta un elemento del lado izquierdo;
deque([<iterable>[, maxlen]])
Ejemplo:
cola = deque("1")
cola.appendleft("0")
cola.pop()
# "2"
cola.popleft()
# "0"
NamedTuple
Las namedtuple nos permiten crear tuplas con nombres, facilitan el acceso a los elementos de una
tupla y el manejo de estos objetos usando propiedades, en lugar de índices. Mejorarán enormemente
6
la legibilidad de tu código, tanto para ti como para tu equipo.
En una tupla normal tendríamos que usar índices para acceder a los valores. El problema con esta
aproximación es que necesitas conocer el índice correcto de antemano para acceder a las propiedades
de las tuplas, lo cual coloca la responsabilidad de saber que atributo representa cada número en el
desarrollador.
producto[0]
producto[1]
# 200
Pero si, en lugar de una tupla normal, usamos una tupla con nombre, podemos tratarla como si se
tratara de un objeto, accediendo a los nombres de las propiedades, en lugar de a sus índices.
libro
libro.precio
# 200
Python se caracteriza por ser un lenguaje lento, en lugar de reescribir los cuellos de botella en un
lenguaje de bajo nivel o cambiar por completo el código, quizás prefieras refactorizar cualquier código
que no sea tan eficiente, pero para eso necesitas medirlo primero. Son pocos los desarrolladores que
saben sobre las herramientas de perfilado que existen en Python y lo sencillas de usar que son.
timeit
Timeit se encarga de repetir múltiples veces una función para calcular el tiempo que consume.
7
Podemos perfirlar el código Python desde la terminal.
import timeit
# 0.20822427999974025
Con el parámetro number podemos aumentar o disminuir el número de repeticiones a nuestro gusto.
Cprofile
Cprofile va a recibir una función a ejecutar y nos imprimirá una tabla donde se muestran la trazabili-
dad de las funciones que se ejecutaron, el número de veces, la duración de la ejecución y el tiempo
import cProfile
import re
cProfile.run('re.compile("foo|bar")')
Como ya sabes, Python no cuenta con las palabras reservadas private y protected para limitar el acceso
a los atributos de un miembro de una clase de manera “real”. Sin embargo existe una convención muy
Colocar un guión bajo antes de un atributo indica que su uso debe ser interno, sin embargo el intér-
prete de Python forzará que se respete esto. Es más una especie de nota para los desarrolladores que
trabajen en tu código que les dice que no deben acceder a la variable desde fuera.
class Persona:
def __init__(self):
self._name = "Nombre"
8
Si intentamos acceder a esta propiedad no pasará nada.
persona = Persona()
persona._name
# Nombre
Un doble guión bajo antes de una propiedad indica que una prohibición al acceso de un atributo fuera
de este, el intérprete de Python si fuerza que se respeta. ¿Cómo lo consigue? Python cambian el
nombre de cualquier atributo que empiece por dos guoines bajos para que no pueda accederse de
manera directa.
Ejemplo:
class Persona:
def __init__(self):
self._name = "Nombre"
Si intentamos acceder directamente al atributo con el nombre de atributo que usamos obtendremos
persona = Persona()
persona.__secret_name
print(persona.__secret_name)
Pero si revisamos todos los atributos de nuestro objeto, con la función dir, veremos que realmente la
variable ha sido renombrada usando la siguiente sintaxis ___, en este caso *_Persona__secret_name*.
Si intentas acceder al atributo usando ese nombre podrás acceder al contenido, pero no deberías, de-
spués de todo alguien uso el doble guión bajo para que no lo hicieras.
9
dir(persona)
Cuando usamos el módulo time para medir el tiempo en Python, Python toma la referencia al tiempo del
sistema. Esto está bien para la mayoría de los casos, pero imagínate que tienes un proceso muy largo y
hay alguien jugando con el tiempo del sistema, lo anterior echaría a perder tu medición por completo.
Para usar un tiempo “real”, que no dependa del tiempo del sistema, usamos el tiempo monotónico.
import time
inicio = time.monotonic()
final = time.monotonic()
print(final - inicio)
Dataclasses
Es bastante común la inicialización de objetos con atributos personalizables, que pasa un usuario. El
class Cuenta:
self.username = username
self.nombre = nombre
self.edad = edad
Esto está bastante bien, pero podemos tener una sintaxis más limpia usando el decorador dataclass. El
10
class Cuenta:
username: str
nombre: str
edad: int
Desestructuración de iterables
Igual que en Javascript podemos desestructurar un iterable, para crear una copia o extender otro iter-
able.
Listas
Para desestructurar una lista, usamos el operador de desestructurización, el asterisco, antes de la ref-
erencia a la lista.
arr = [1, 2, 3]
otro_arr = [*arr]
arr = [1, 2, 3]
arr2 = [4, 5, 6]
Sets
De la misma manera que los arrays, los sets pueden desestructurarse siguiendo la misma sintaxis.
sett1 = {1, 2, 3, 4}
sett2 = {4, 5, 6, 7}
11
Diccionarios
Para desestructurar un diccionario lo haremos igual que una lista, pero usando dos asteriscos, en lugar
de uno.
nuevo_dict = { **primer_dict }
De la misma manera, podemos desestructurar tantos diccionarios como querramos para crear otro
Los métodos mágicos no tienen nada de mágicos, pero te ayudan a personalizar el comportamiento
Puedes entenderlos como métodos especiales de un objeto que se ejecutan solo bajo ciertas condi-
ciones. Por ejemplo: cuando se crea una instancia de un objeto, o cuando se establece un atributo, o
Su sintaxis es la siguiente:
def __<nombre_del_metodo>__(self):
pass
Puedes pensar en el doble guión al principio como una señal de que no debes llamarlos de manera
directa, sino que se llamarán “solos” cuando tu realices acciones sobre el objeto que las implementa.
Uno de los más conocidos, se llama cuando se ejecuta el método print sobre un objeto. En Django se
class MagicMethods(object):
def __str__(self):
12
magic = MagicMethods()
print(magic)
Init se llama cuando se inicializa una instancia de un objeto, es el método ideal para asignar atributos
class MagicMethods(object):
self.primer_argumento = args[0]
print("Inicializando el objeto")
# Inicializando el objeto
Se llama cuando se establece un atributo. Tiene dos compañeros: ### __getattr__ y ### __delattr__,
que se llaman cuando se intenta acceder a un atributo que no existe y cuando se intenta borrar un
atributo, respectivamente.
class Persona(object):
self.name = name
13
self.__dict__[name] = value
Cuando creamos el objeto, se establecerá el atributo y se llamará __setattr__. Mira como accedemos
al método mágico *__dict__*, puesto que si hicieramos la asignación de manera normal entrariamos en
un bucle infinito.
__getattr__ se llama si intentamos acceder an atributo que no existe, dentro de este método seremos
class Persona(object):
# ...
a.atributo_inexistente
# no existe
__delattr__ se llama cuando intentamos eliminar un atributo de un objeto, dentro del método podemos
personalizar el comportamiento, desde notificar sobre esto o bloquear por completo el bloqueo.
class Persona(object):
# ...
14
def __delattr__(self, name):
del self.__dict__[name]
Los siguientes métodos generalmente se utilizan juntos y son muy útiles al momento de crear iter-
adores personalizados. Imagínate un iterador que genere potencias de dos, o números primos, o
__iter__ Este método se llama cuando se crea un iterador, normalmente retornamos el mismo objeto,
a través de self, para que en cada una de las siguientes interacciones podamos llamar a su método
__next__
class StringIncremental():
def __iter__(self):
self.cadena = ""
return self
__next__ __next__ se llama en cada una de las iteraciones de un objeto. Hay que recordar que este
método tiene que levantar una excepción para avisarle a nuestro ciclo que debe terminar y evitar bucles
infinitos.
class StringIncremental():
def __iter__(self):
self.cadena = ""
return self
def __next__(self):
15
self.cadena += "a"
if len(self.cadena) > 4:
raise StopIteration
return self.cadena
iterador = StringIncremental()
print(letra)
# a
# aa
# aaa
# aaaa
# Se termina la iteración
Si has visto esta comprobación en algunos scripts de Python y no entiendes como funciona.
if __name__=='__main__':
Este pequeño trozo de código se usa para que solo se ejecute el código si lo pasamos directamente al
__name__
El intérprete de Python asigna automáticamente un nombre a cada archivo que ejecuta y lo guarda en
una variable de nombre __name__. ¿Te fijas que en ningún momento declaramos __name__?
# libreria.py
return a + b
16
print(__name__)
# main.py
import libreria
Si usamos el intérprete de Python para ejecutar el archivo, observaremos que la función print se ejecu-
python main.py
# libreria
’__main__’
Cuando ejecutamos un archivo de Python usando el intérprete, este le asigna el string ’__main__’ a la
# main.py
print(__name__)
python main.py
# __main__
¿Y esto en que nos sirve? Es bastante útil para saber si el archivo en el que estamos está siendo ejecu-
Por otro lado, si el archivo no está siendo importado, es decir, está siendo ejecutado directamente por
if __name__== '__main__':
main()
17
Crea tu propio context manager
¿Recuerdas esa sintaxis de Python que te permite cerrar automáticamente el stream de archivos?
contenido = f.readlines()
Con esta sintaxis ya no tienes que llamar al método f.close() para cerrar el archivo, Python lo hace
Con Python tú también puedes crear tus propias clases que sirvan como context manager. Estas
pueden servirte para cerrar conexiones a base de datos, conexiones HTTP pendientes, o cualquier
• exit() Se ejecuta cuando se abandona el contexto de ejecución, es decir, al salir del bloque with.
class context_manager():
def __enter__(self):
print("Bienvenido al contexto")
print("Abandonando el contexto")
Al ejecutar nuestra nueva clase en un contexto usando with verás lo que sucede
print(ctx)
# Bienvenido al contexto
# Abandonando el contexto
18
¿Qué acaba de pasar? Te explico lo que sucede al ejecutar nuestro bloque with en orden:
2. La función enter termina de ejecutarse y devuelve un valor que se imprime con la función print
Habrás notado que la función exit tiene una serie de argumentos especiales. Los parámetros que recibe
la función se usan para manejar excepciones. Cuando una excepción ocurre, exc_type, exc_value, and
Python es un lenguaje interpretado y que no destaca precisamente por su velocidad. Debido a lo ante-
rior, otros desarrolladores se han dado la tarea de crear alternativas mejoradas al intérprete predeter-
Se usan exactamente igual que usarías el intérprete normal, pero algunos no son totalmente compati-
bles con todo el código Python, por lo que asegúrate de revisar sus limitaciones y casos de uso en sus
• PyPy
• Stackless Python
• Jython
• IronPython
• GraalPython
¿Preocupado por el rendimiento de Python? Swig es una herramienta que te permite escribir código
en C o C++ y, posteriormente, llamarlo desde Python. El proceso es algo tedioso, pero muy mecánico,
no hay que pensar demasiado, solo hay que ejecutar una serie de comandos (que no cubriré aquí) tras
lo cual tendrás una librería importable que funciona usando código compilado que te ofrecerá lo mejor
de los dos mundos: la legibilidad de un lenguaje de alto nivel, con la velocidad de un lenguaje de bajo
nivel.
Con lo anterior doy por terminado esta pequeña guía de trucos de Python.
19
Nos vemos la siguiente semana en tu bandeja de entrada.
20