Loading

Python Backend

Pedro Flores

This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.

{python backend}

101 Super Mega Turbo Diesel Intercooler XP 2000 Recargado Endgame Begginer Pack

{python} backend?

En realidad python refreshener y si da el tiempo backend flask en python

Para seguir la presentación desde su notebook,

celular,

tablet,

tostadora...

# CONTENIDO
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primera app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
  • Herencia de clases
  • Class composition
  • Type hinting en Python 3.5+
  • Imports en Python
  • Imports relativos en Python
  • Errores in Python
  • Errores personalizados
  • Funciones First-class
  • Simple decorators en Python
  • La sintaxis 'at' para los decorators
  • Decorators en funciones con parámetros
  • Decorators con parameters
  • Mutability en Python
  • Mutable default parameters (y porqué son una mala idea)
# CONTENIDO
  • Tu primera API REST
    • Access the course e-book here
    • Configuración inicial para una app Flask
    • Tu primer endpoint de tu API REST
    • ¿Qué es JSON?
    • Como interactuar y probar tu API REST
    • Como crear tiendas en nuestra API REST
    • Como crear items en cada tienda
    • Como obtener una tienda y sus items
  • Almacenar datos en una base de datos SQL
    • Acerca de y porqué usar SQLAlchemy
    • Como codificar un modelo simple en SQLAlchemy
    • Como escribit relaciones uno a muchos en SQLALchemy
    • Como configurar Flask-SQLAlchemy en tu app Flask
    • Como insertar datos en una tabla usando SQLALchemy
    • Como encontrar modelos en la BD por ID o retornar 404
    • Como actualizar modelos en SQLALchemy
    • Como obtener la lista de todos los modelos
    • Como borrar modelos con SQLAlchemy
  • Relaciones "Mucho-a-mucho" con SQLALchemy
    • Cambios en esta sección
    • Relaciones "uno-a-muchos" entre tiendas y etiquetas
    • Relaciones "mucho-a-mucho" entre tiendas y etiquetas

Sobre mi

 @neowinx

Pedro Flores

}

# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
  • Herencia de clases
  • Class composition
  • Type hinting en Python 3.5+
  • Imports en Python
  • Imports relativos en Python
  • Errores in Python
  • Errores personalizados
  • Funciones First-class
  • Simple decorators en Python
  • La sintaxis 'at' para los decorators
  • Decorators en funciones con parámetros
  • Decorators con parameters
  • Mutability en Python
  • Mutable default parameters (y porqué son una mala idea)
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# INSTALACIÓN

Para instalar Python, descargar Python 3.10 (o mayor) de http://www.python.org/

Es muy importante: al instalar, hacer check en "Add Python to PATH"

# INSTALACIÓN

Si se tiene varias versiones de Python instaladas, como las que se instalaron anteriormente, pueden listar las mismas con este comando:

py -0p

El resultado seria algo como esto:

C:\Users\youruser>py -0p
Installed Pythons found by py Launcher for Windows
 -3.10-64       C:\Users\youruser\AppData\Local\Programs\Python\Python310\python.exe *
 -3.9-64        C:\Users\youruser\AppData\Local\Programs\Python\Python39\python.exe
 -3.8-64        C:\Users\youruser\AppData\Local\Programs\Python\Python38\python.exe
 -3.7-64        C:\Users\youruser\AppData\Local\Programs\Python\Python37\python.exe
 -3.7-32        C:\Program Files (x86)\Python37-32\python.exe
 -2.7-64        C:\Python27\python.exe

El resultado seria algo como esto:

C:\Users\youruser>py -0p
Installed Pythons found by py Launcher for Windows
 -3.10-64       C:\Users\youruser\AppData\Local\Programs\Python\Python310\python.exe *
 -3.9-64        C:\Users\youruser\AppData\Local\Programs\Python\Python39\python.exe
 -3.8-64        C:\Users\youruser\AppData\Local\Programs\Python\Python38\python.exe
 -3.7-64        C:\Users\youruser\AppData\Local\Programs\Python\Python37\python.exe
 -3.7-32        C:\Program Files (x86)\Python37-32\python.exe
 -2.7-64        C:\Python27\python.exe

Una vez identificada la version que quieren usar: 

py -3.9 file_to_run.py
# INSTALACIÓN
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Variables en Python
# -- Numeros y flotantes --

x = 15
price = 9.99

discount = 0.2

result = price * (1 - discount)

print(result)

# -- Cadenas de texto (Strings) --

name = "Rolf"
name = "Rolf"

print(name)
print(name * 2)
# Variables en Python
# -- Cambiando variables --
# Las variables son nombres de valores

a = 25
b = a

# Aqui le dimos el valor '25' a los nombres 'a' y 'b'.

print(a)
print(b)

b = 17

# Aquí le dimos el valor '17' y el nombre 'b'. El nombre 'a' sigue siendo el nombre del valor '25'!

print(a)
print(b)
# Variables en Python

Ejercicio:

 

# Crear dos variables, var1 y var2, ambos con el mismo valor.


# Crear dos variables, num1 y num2, cuyo multiplo es igual a 16.

# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# STRINGS
nombre = "Pedro"
saludo = "Hola, Pedro"

print(saludo)

nombre = "Rafa"

print(saludo)

saludo = f"Hola, {nombre}"
print(saludo)
nombre = "Ana"
print(
    saludo
)  # Esto imprime "Hola, Rafa" porque `saludo` se calculo antes.

print(
    f"Hola, {nombre}"
)  # Esto es incorrecto debido a que usa `nombre` en el punto actual en el tiempo.
# STRINGS
# -- Usando .format() --

# Podemos definir 'template strings' que reemplacen partes del mismo con otros valores en vez de hacerlo directamente en la cadena.

saludo = "Hola, {}"
con_nombre = saludo.format("Rafa")
print(con_nombre)

frase_mas_larga = "Hola, {}. hoy es {}."
formateado = frase_mas_larga.format("Rafa", "Lunes")
print(formateado)
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# ENTRADA DEL USUARIO
nombre = input("Ingrese su nombre: ")
print(nombre)

# -- Matemáticas en la entrada de usuario --

size_input = input("Que tan grande es tu casa (en metros cuadrados): ")
square_feet = int(size_input)
square_metres = square_feet * 10.8  # Verificar este valor
print(f"{square_feet} metros cuadrados es {square_metres} pies cuadrados.")
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# PRIMER APP
user_age = input("Enter your age: ")
age_number = int(user_age)

months = age_number * 12
print(f"{age_number} is equal to {months} months.")
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Listas, tuplas y conjuntos
l = ["Bob", "Rolf", "Anne"]
t = ("Bob", "Rolf", "Anne")
s = {"Bob", "Rolf", "Anne"}

# Acceder a items individuales en las listas y tuplas utilizando el índice.

print(l[0])
print(t[0])
# print(s[0])  # Esto da un error porque los conjuntos no mantienen el orden, por lo que acceder al elemento con indice 0 no tiene sentido.

# Modificar items individuales en las listas utilizando el índice.
l[0] = "Smith"
# t[0] = "Smith"  # Esto da un error debido a que las tuplas son "inmutables"

print(l)
print(t)

# Anexar elemento a la lista utilizando `.append`
l.append("Jen")
print(l)

# Las tuplas no pueden anexar items debido a que son inmutables.

# Agregar items a un conjunto utilizando `.add`
s.add("Jen")
print(s)

# Los conjuntos no pueden tener el mismo elemento más de una vez
s.add("Bob")
print(s)
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Booleans en Python
# -- Comparaciones --

print(5 == 5)  # True
print(5 > 5)  # False
print(10 != 10)  # False

# Comparaciones: ==, !=, >, <, >=, <=

# -- is --
# Python tambien tiene la palabra reservada `is`. En general no se recomienda usar ya que es un tanto confusa

friends = ["Rolf", "Bob"]
abroad = ["Rolf", "Bob"]

print(friends == abroad)  # True
print(friends is abroad)  # False
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Sentencia "if"
dia = input("¿Qué día de la semana es hoy?")

if dia == "Lunes":
    print("Que tengas un muy buen inicio de semana!")
elif dia == "Viernes":
    print("Esta bien terminar un poco antes hoy!")
else:
    print("A toda marcha!")

# -- Problema: el usuario no ingrese lo que esperamos --

dia = input("¿Qué día de la semana es hoy? ").lower()

if dia == "lunes":
    print("Que tengas un muy buen inicio de semana!")
elif dia == "viernes":
    print("Esta bien terminar un poco antes hoy!")
else:
    print("A toda marcha!")
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod

# Palabra clave "in"

amigos = ["Rafa", "Blas", "Jazmin"]
print("Jazmin" in friends)

# --

peliculas_miradas = {"The Matrix", "Green Book", "Her"}
peli_de_usuario = input("Ingresa algo que hayas mirado recientemente: ")

print(peli_de_usuario in peliculas_miradas)

# La palabra `in` se encuentra en la mayoria de las secuencias como listas, tuplas y conjuntos.
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod

# Sentencias "if" con "in"

# Ejemplo1

pelis_vistas = {"The Matrix", "Green Book", "Her"}
peli_de_usuario = input("Ingresa algo que hayas visto recientemente: ")

if peli_de_usuario in pelis_vistas:
    print(f"Yo he visto {peli_de_usuario} también!")
else:
    print("Aún no he visto esa.")

# Sentencias "if" con "in"

# Ejemplo 2

numero = 7
entrada_usuario = input("Ingrese 's' si te gustaria jugar:")

if entrada_usuario in ("s", "S"):
    numero_del_usuario = int(input("Adivina el número: "))
    if numero_del_usuario == numero:
        print("Has adivinado!")
    elif numero - numero_del_usuario in (1, -1):
        print("Fallaste por 1.")
    else:
        print("Lo siento, número equivocado")

# Sentencias "if" con "in"

# Ejemplo 2

numero = 7
entrada_usuario = input("Ingrese 's' si te gustaria jugar:")

if entrada_usuario in ("s", "S"):
    numero_del_usuario = int(input("Adivina el número: "))
    if numero_del_usuario == numero:
        print("Has adivinado!")
    elif numero - numero_del_usuario in (1, -1):
        print("Fallaste por 1.")
    else:
        print("Lo siento, número equivocado")


# Tambien podemos hacer una transformación en vez de checkear cada opción.

numero = 7
entrada_usuario = input("Ingrese 's' si te gustaria jugar:")

if entrada_usuario.lower() == "s":
    numero_del_usuario = int(input("Adivina el número: "))
    if numero_del_usuario == numero:
        print("Has adivinado!")
    elif abs(numero - numero_del_usuario) == 1:
        print("Fallaste por 1.")
    else:
        print("Lo siento, número equivocado")
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod

# Loops en Python

# -- While loop --

number = 7
play = input("Would you like to play? (Y/n) ")

while play != "n":
    user_number = int(input("Guess our number: "))
    if user_number == number:
        print("You guessed correctly!")
    elif abs(number - user_number) == 1:
        print("You were off by 1.")
    else:
        print("Sorry, it's wrong!")

    play = input("Would you like to play? (Y/n) ")

# Loops en Python

# -- The break keyword --

while True:
    play = input("Would you like to play? (Y/n) ")

    if play == "n":
        break  # Exit the loop

    user_number = int(input("Guess our number: "))
    if user_number == number:
        print("You guessed correctly!")
    elif abs(number - user_number) == 1:
        print("You were off by 1.")
    else:
        print("Sorry, it's wrong!")

# Loops en Python

# -- For loop --

friends = ["Rolf", "Jen", "Bob", "Anne"]
for friend in friends:
    print(f"{friend} is my friend.")

# -- For loop 2 -- Average

grades = [35, 67, 98, 100, 100]
total = 0
amount = len(grades)

for grade in grades:
    total += grade

print(total / amount)

# -- Rewritten using sum() --

grades = [35, 67, 98, 100, 100]
total = sum(grades)
amount = len(grades)

print(total / amount)

# You kinda just have to "know" that exists. It takes time and experience, but searching for almost _everything_ really helps. For example, you could've searched for "sum list of numbers python".
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod

# Comprensión de listas en Python

numeros = [1, 3, 5]
cuadrados = [x * 2 for x in numeros]

# -- Manejando cadenas de texto --

amigos = ["Rafa", "Sam", "Samantha", "Sabrina", "Jazmin"]
comienzan_s = []

for amigo in amigos:
    if amigo.startswith("S"):
        comienzan_s.append(amigo)

print(comienzan_s)

# -- Podemos crear una nueva lista de amigos con nombres que comiencen con S --

amigos = ["Rafa", "Samu", "Samantha", "Sabrina", "Jazmin"]
comienzan_s = [ami for ami in amigos if ami.startswith("S")]

print(comienzan_s)

# -- List comprehension creara una _nueva_ lista --

amigos = ["Samu", "Samantha", "Sabrina"]
comienzan_s = [ami for ami in amigos if ami.startswith("S")]  # same as above

print(amigos)
print(comienzan_s)
print(amigos is comienzan_s)
print("friends: ", id(amigos), " starts_s: ", id(comienzan_s))
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Diccionarios
edad_de_amigos = {"Rafa": 24, "Alan": 30, "Ana": 27}

edad_de_amigos["Blas"] = 20

print(edad_de_amigos)  # {'Rafa': 24, 'Alan': 30, 'Ana': 27, 'Blas': 20}
print(edad_de_amigos["Bob"])

# -- Lista de diccionarios --

amigos = [
    {"name": "Rolf Smith", "age": 24},
    {"name": "Adam Wool", "age": 30},
    {"name": "Anne Pun", "age": 27},
]

print(amigos)
# Diccionarios
# -- Iteración --

asistencia_estudiantes = {"Rolf": 96, "Bob": 80, "Anne": 100}

for estudiante in asistencia_estudiantes:
    print(f"{estudiante}: {asistencia_estudiantes[estudiante]}")

# Mejor

for estudiante, asistencia in asistencia_estudiantes.items():
    print(f"{estudiante}: {asistencia}")

# -- Usando la palabra reservada `in` --

if "Bob" in asistencia_estudiantes:
    print(f"Bob: {asistencia_estudiantes[estudiante]}")
else:
    print("Bob isn't a estudiante in this class!")

# -- Calcular el promedio con `.values()` --

asistencias = asistencia_estudiantes.values()
print(sum(asistencias) / len(asistencias))
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod

# De-estructuración de variables

x, y = 5, 11

# x, y = (5, 11)

# -- Deestructuración en for loops --

asistencia_estudiantes = {"Rafa": 96, "Blas": 80, "Ana": 100}

for estudiante, asistencia in asistencia_estudiantes.items():
    print(f"{estudiante}: {asistencia}")


# -- Otro ejemplo --

gente = [("Blas", 42, "Mecanico"), ("Jaime", 24, "Artista"), ("Hugo", 32, "Profesor")]

for nombre, edad, profesion in gente:
    print(f"Nombre: {nombre}, Edad: {edad}, Profesion: {profesion}")

# -- Mucho mejor que esto! --

for persona in gente:
    print(f"Nombre: {persona[0]}, Edad: {persona[1]}, Profesion: {persona[2]}")

# De-estructuración de variables

# -- Ignorar valores con guion bajo --

persona = ("Blas", 42, "Mecanico")
nombre, _, profesion = persona

print(nombre, profesion)  # Blas Mecanico


# -- Recolectando valores --

cabeza, *cola = [1, 2, 3, 4, 5]

print(cabeza)  # 1
print(cola)  # [2, 3, 4, 5]


*cabeza, cola = [1, 2, 3, 4, 5]

print(cabeza)  # [1, 2, 3, 4]
print(cola)  # 5

# -- Packing y unpacking --

# Existen también formas de desempaquetar y empaquetar collections usando * y **, pero eso es un poco más avanzado y lo aprenderemos más adelante!
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Funciones en Python
def hola():
    print("Hola!")


hola()

# -- Definicion vs. llamada --
# Sige siendo todo secuencial!


def edad_del_usuario_en_segundos():
    edad_usuario = int(input("Ingresa tu edad: "))
    edad_segundos = edad_usuario * 365 * 24 * 60 * 60
    print(f"Tu edad en segundos es {edad_segundos}.")


print("Bienvenido al programa 'edad en segundos'!")
edad_del_usuario_en_segundos()

print("Adios!")
# Funciones en Python
# -- No reusen nombres --
def print():
    print("Hola mundo")  # Error!


# -- No reusen nombres, es generalmente confuso! --
amigos = ["Rafa", "Blas"]


def agregar_amigo():
    nombre_amigo = input("Ingresa el nombre de tu amigo: ")
    amigos = amigos + [nombre_amigo]  # Otra forma de agregar items a una lista!


agregar_amigo()
print(amigos)  # Siempre ['Rafa', 'Blas']
# Funciones en Python
# -- No llames a una funcion antes de haberla definido --
decir_hola()


def decir_hola():
    print("Hola!")


# -- Recuerda que el cuerpo de la funcion solo se ejecuta cuando se llama --


def agregar_amigo():
    amigos.append("Rafa")


amigos = []
agregar_amigo()

print(amigos)  # [Rafa]
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Argumentos y parámetros de funciones
def sumar(x, y):
    resultado = x + y
    print(resultado)


sumar(2, 3)  # 5

# -- Si una funcion no tiene parametros, no puedes pasarle ningun argumento--


def decir_hola():
    print("Hola!")


decir_hola("Bob")  # Error

# -- Pero si agregas un parametro, entonces debes pasar el argumento --


def decir_hola(nombre):
    print(f"Hola, {nombre}!")


decir_hola("Bob")
decir_hola()  # Error, needs an argument
# Argumentos y parámetros de funciones

# -- Keyword arguments --
# Para hacer las cosa más claras, en Python uno puede pasar argumentos con nombre (Keyword arguments) 


def decir_hola(nombre):
    print(f"Hello, {nombre}!")


decir_hola(name="Bob")  # Es obvio que debe ser le nombre de alguien


def dividir(dividendo, divisor):
    if divisor != 0:
        print(dividendo / divisor)
    else:
        print("Que tonto!")


dividir(dividendo=15, divisor=3)
dividir(15, 0)
dividir(15, divisor=0)  # OK
# divide(dividend=15, 0)  # No OK, los argumentos con nombre deben ir despues de los argumentos por posicion

# Es recomendable utilizar argumentos con nombre siempre que se pueda, principalmente porque hacen el código cosas más legible a largo plazo.
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod

# Funciones con valores de retorno

def sumar(x, y):
    print(x + y)

sumar(5, 8)
resultado = sumar(5, 8)
print(resultado)  # None

# Si queremos obtener algo desde la funcion, la misma debe retornar un valor.
# Todas las funciones retornan _algo_. Por defecto, lo que retorna es 'None'.

# -- Retornando valores --

def sumar(x, y):
    return x + y

sumar(1, 2)  # Ya no imprime nada
resultado = sumar(2, 3)
print(resultado)  # 5

# Funciones con valores de retorno

# -- Al retornar, la función termina su ejecución --

def sumar(x, y):
    return
    print(x + y)
    return x + y

resultado = sumar(5, 8)  # No se imprime nada
print(resultado)  # None, debido a que es el primer 'return'

# -- Retornar con condicionales --

def dividir(dividendo, divisor):
    if divisor != 0:
        return dividendo / divisor
    else:
        return "Que tonteria!"

resultado = dividir(15, 3)
print(resultado)  # 5

otro_resultado = dividir(15, 0)
print(otro_resultado)  # Que tonteria!
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Funciones Lambda
def sumar(x, y):
    return x + y


print(sumar(5, 7))

# -- Written as a lambda --
# -- Escrito como funcion lambda --

sumar = lambda x, y: x + y
print(sumar(5, 7))
# Funciones Lambda
# Cuatro partes
# lambda
# parametros
# :
# valor retornado

# Las funciones Lambdas suelen ser cortas, generalmente utilizadas sin darles un nombre.
# Por ejemplo, en conjunción con la función estandar map
# map aplica la función lambda a todos los valores de la secuencia


def doble(x):
    return x * 2


secuencia = [1, 3, 5, 9]

dobles = [
    doble(x) for x in secuencia
]  # Coloca el resultado de doble(x) en una nueva lista, por cada uno de los valores en `secuencia`
dobles = map(doble, secuencia)
print(list(dobles))

# -- Escrito como lambda --

secuencia = [1, 3, 5, 9]

dobles = map(lambda x: x * 2, secuencia)
print(list(dobles))
# Funciones Lambda
def doble(x):
    return x * 2


secuencia = [1, 3, 5, 9]

dobles = [
    doble(x) for x in secuencia
]  # Coloca el resultado de doble(x) en una nueva lista, por cada uno de los valores en `secuencia`
dobles = map(doble, secuencia)
print(list(dobles))

# -- Escrito como lambda --

secuencia = [1, 3, 5, 9]

dobles = map(lambda x: x * 2, secuencia)
print(list(dobles))

# -- Importante recordar --
# Lambdas son simplemente funciones sin nombre.
# Son utilizadas para retornar un valor calculado desde sus párametros.
# Casi siempre son de una linea, para no hacer nada complicado en ellas.
# Muy amenudo es mejor simplemente definir una funcion y darle un nombre propio.
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Dictionary comprehensions
usuarios = [
    (0, "Bob", "password"),
    (1, "Rolf", "bob123"),
    (2, "Jose", "longp4assword"),
    (3, "username", "1234"),
]

username_mapping = {user[1]: user for user in usuarios}
userid_mapping = {user[0]: user for user in usuarios}

print(username_mapping)

print(username_mapping["Bob"])  # (0, "Bob", "password")

# -- Puede ser util para el login por ejemplo--

username_input = input("Ingrese su usuario: ")
password_input = input("Ingrese su password: ")

_, username, password = username_mapping[username_input]

if password_input == password:
    print("Detalles correctos!")
else:
    print("Sus detalles son incorrectos.")

# Si nosotros no usabamos el mapping, el codigo iba a requerir que iterasemos todos los usuarios.
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Unpacking arguments
def multiplicar(*args):
    print(args)
    total = 1
    for arg in args:
        total = total * arg

    return total


print(multiplicar(3, 5))
print(multiplicar(-1))

# El asterisco toma todos los argumentos y los empaqueta (pack) en una tupla.
# El asterisco tambien puede usarse para desempaquetar (unpack) secuencias en argumentos!


def sumar(x, y):
    return x + y


nums = [3, 5]
print(sumar(*nums))  # en vez de sumar(nums[0], nums[1])
# Unpacking arguments
# -- Usos con argumentos con nombre --
# Doble asterisco empaquta y desempaqueta argumentos con nombre


def sumar(x, y):
    return x + y


nums = {"x": 15, "y": 25}

print(sumar(**nums))
# Unpacking arguments
# -- Usos con argumentos con nombre --
# Doble asterisco empaquta y desempaqueta argumentos con nombre


def sumar(x, y):
    return x + y


nums = {"x": 15, "y": 25}

print(sumar(**nums))


# -- Forzar un parámetro con nombre --

def multiplicar(*args):
    total = 1
    for arg in args:
        total = total * arg

    return total


def aplicar(*args, operador):
    if operador == "*":
        return multiplicar(args)
    elif operador == "+":
        return sum(args)
    else:
        return "No se ha proveído un operador válido a aplicar()."


print(aplicar(1, 3, 6, 7, operador="+"))
print(aplicar(1, 3, 5, "+"))  # Error
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Unpacking keyword arguments
# -- Unpacking kwargs --
def named(**kwargs):
    print(kwargs)


named(name="Bob", age=25)
# named({"name": "Bob", "age": 25})  # Error, el diccionario es realmente un argumento posicional.

# Desempaquetar un dict en argumentos. Esto funciona, pero es un poco más confuso. Aunque cuando se trabaja con variables está bien.
named(**{"name": "Bob", "age": 25})


# -- Unpacking and repacking --
def named(**kwargs):
    print(kwargs)


def imprimir_lindo(**kwargs):
    named(**kwargs)  # Desempaquetar el diccionario en argumentos por nombres.
    for arg, value in kwargs.items():
        print(f"{arg}: {value}")


imprimir_lindo(name="Bob", age=25)
# Unpacking keyword arguments
# -- Ambos args y kwargs --


def ambos(*args, **kwargs):
    print(args)
    print(kwargs)


ambos(1, 3, 5, name="Bob", age=25)

# Estos se usa generalmente para aceptar un número ilimitado de argumentos por posicion y por nombres, como para poder pasar alguno de ellos a otras funciones.
# Frequentemente se ven cosas como ésta en código Python:

"""
def post(url, data=None, json=None, **kwargs):
    return request('post', url, data=data, json=json, **kwargs)
"""

# La implementación en este punto es irrelevante, lo que permite es que el que llama a la función `post()` pueda pasar argumentos a `request()`.

# -- Error when unpacking --


def myfunction(**kwargs):
    print(kwargs)


myfunction(**"Bob")  # Error, debe estar mapeado
myfunction(**None)  # Error
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# Programación orientada a objetos en Python
estudiante = {"name": "Rolf", "grades": (89, 90, 93, 78, 90)}


def promedio(secuencia):
    return sum(secuencia) / len(secuencia)


print(promedio(estudiante["grades"]))

# Pero no seria lindo si pudiesemos...
# print(estudiante.promedio()) ?


class Estudiante:
    def __init__(self):
        self.nombre = "Rolf"
        self.puntajes = (89, 90, 93, 78, 90)

    def promedio(self):
        return sum(self.puntajes) / len(self.puntajes)


estudiante = Estudiante()
print(estudiante.promedio())
# Identico a Estudiante.promedio(estudiante)
# Programación orientada a objetos en Python
# -- Parameters in __init__ --


class Estudiante:
    def __init__(self, nombre, puntajes):
        self.nombre = nombre
        self.puntajes = puntajes

    def promedio(self):
        return sum(self.puntajes) / len(self.puntajes)


estudiante = Estudiante("Bob", (36, 67, 90, 100, 100))
print(estudiante.average())

# -- Se acuerdan de *args ? --

class Estudiante:
    def __init__(self, nombre, *puntajes):
        self.nombre = nombre
        self.puntajes = puntajes

    def promedio(self):
        return sum(self.puntajes) / len(self.puntajes)


estudiante = Estudiante("Bob", 36, 67, 90, 100, 100)
print(estudiante.promedio())
# Programación orientada a objetos en Python
# Funciones vs. Métodos 

Una función que reside dentro de una clase es llamada método.

Por lo tanto, los métodos son funciones, pero no todas las funciones son métodos.

## Función

def promedio(secuencia):
    return sum(secuencia) / len(secuencia)

## Método

class Estudiante:
    def __init__(self):  # método
        self.nombre = "Rolf"
        self.puntajes = (79, 90, 95, 99)
    
    def promedio(self):  # método
        return sum(self.puntajes) / len(self.puntajes)
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
# @classmethod y @staticmethod
class ClassTest:
    def metodo_de_instancia(self):
        print(f"Se ha llamado al instance_method de {self}")

    @classmethod
    def metodo_de_clase(cls):
        print(f"Se a llamado al class_method de {cls}")

    @staticmethod
    def metodo_estatico():
        print(f"Se ha llamado al static_method."
              "Aquí no obtenemos ni la instancia del objeto, ni la clase.")


instancia = ClassTest()
instancia.metodo_de_instancia()

ClassTest.metodo_de_clase()
ClassTest.metodo_estatico()

# -- ¿Para qué se usan? --

# - Los métodos de instancia son utilizados para todas las operaciones con la instancia que utilicen sus datos.
# - Los métodos de clase son métodos que se usan para operaciones con la clase. Son utilizados generalmente como factories.
# - Los métodos estáticos sno utilizados para colocar métodos dentro de la clase por organización de código más que nada.
# @classmethod y @staticmethod
# -- ¿Para qué se usan? --

# - Los métodos de instancia son utilizados para todas las operaciones con la instancia que utilicen sus datos.
# - Los métodos de clase son métodos que se usan para operaciones con la clase. Son utilizados generalmente como factories.
# - Los métodos estáticos sno utilizados para colocar métodos dentro de la clase por organización de código más que nada.


class Libro:
    TIPOS = ("tapa_dura", "tapa_blanda")

    def __init__(self, nombre, tipo_libro, peso):
        self.nombre = nombre
        self.tipo_libro = tipo_libro
        self.peso = peso

    def __repr__(self):
        return f"<Libro {self.nombre}, {self.tipo_libro}, pesando {self.peso}g>"

    @classmethod
    def tapa_dura(cls, name, page_weight):
        return cls(name, cls.TIPOS[0], page_weight + 100)

    @classmethod
    def tapa_blanda(cls, name, page_weight):
        return cls(name, cls.TIPOS[1], page_weight)


pesado = Libro.tapa_dura("Harry Potter", 1500)
liviano = Libro.tapa_blanda("Python 101", 600)

print(pesado)
print(liviano)
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
  • Herencia de clases
  • Class composition
  • Type hinting en Python 3.5+
  • Imports en Python
  • Imports relativos en Python
  • Errores in Python
  • Errores personalizados
  • Funciones First-class
  • Simple decorators en Python
  • La sintaxis 'at' para los decorators
  • Decorators en funciones con parámetros
  • Decorators con parameters
  • Mutability en Python
  • Mutable default parameters (y porqué son una mala idea)
# Herencia de clases
class Device:
    def __init__(self, name, connected_by):
        self.name = name
        self.connected_by = connected_by
        self.connected = True

    def __str__(self):
        return f"Device {self.name!r} ({self.connected_by})"

    def disconnect(self):
        self.connected = False


# printer = Device("Printer", "USB")
# print(printer)

# No queremos agregar cosas específicas de printer, por lo tanto...


class Printer(Device):
    def __init__(self, name, connected_by, capacity):
        # super(Printer, self).__init__(name, connected_by)  - Python2.7
        super().__init__(name, connected_by)  # Python3+
        self.capacity = capacity
        self.remaining_pages = capacity

    def __str__(self):
        return f"{super().__str__()} ({self.remaining_pages} pages remaining)"

    def print(self, pages):
        if not self.connected:
            raise TypeError("Device is disconnected at this time, cannot print.")
        print(f"Printing {pages} pages.")
        self.remaining_pages -= pages


printer = Printer("Printer", "USB", 500)
printer.print(20)
print(printer)
printer.print(50)
print(printer)
printer.disconnect()
printer.print(30)  # Error
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
  • Herencia de clases
  • Class composition
  • Type hinting en Python 3.5+
  • Imports en Python
  • Imports relativos en Python
  • Errores in Python
  • Errores personalizados
  • Funciones First-class
  • Simple decorators en Python
  • La sintaxis 'at' para los decorators
  • Decorators en funciones con parámetros
  • Decorators con parameters
  • Mutability en Python
  • Mutable default parameters (y porqué son una mala idea)
# Class composition
# Algo que se ve muy a menudo pero que NO DEBES HACER


class EstanteLibro:
    def __init__(self, cantidad):
        self.cantidad = cantidad

    def __str__(self):
        return f"EstanteLibro con {self.cantidad} libros."


estante = EstanteLibro(300)


class Libro(EstanteLibro):
    def __init__(self, nombre, cantidad):
        super().__init__(cantidad)
        self.nombre = nombre


# Esto no tiene sentido, porque ahora hay que pasar `cantidad` a un solo libro:

libro = Libro("Harry Potter", 120)
print(libro)  # Que?
# Class composition
# -- Composition over inheritance --

# Herencia: "Un Libro es un estante"
# Composicion: "Un estante tiene muchos libos"


class EstanteLibro:
    def __init__(self, *libros):
        self.libros = libros

    def __str__(self):
        return f"EstanteLibro con {len(self.libros)} libros."


class Libro:
    def __init__(self, name):
        self.name = name


libro = Libro("Harry Potter")
libro2 = Libro("Python 101")
estante = EstanteLibro(libro, libro2)
print(estante)
# CONTENIDO
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primer app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Argumentos y parámetros de funciones
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
  • Herencia de clases
  • Class composition
  • Type hinting en Python 3.5+
  • Imports en Python
  • Imports relativos en Python
  • Errores in Python
  • Errores personalizados
  • Funciones First-class
  • Simple decorators en Python
  • La sintaxis 'at' para los decorators
  • Decorators en funciones con parámetros
  • Decorators con parameters
  • Mutability en Python
  • Mutable default parameters (y porqué son una mala idea)
# Type hinting en Python 3.5+
def lista_promedio(secuencia: list) -> float:
    return sum(secuencia) / len(secuencia)

# -- Type hinting clases --

class Libro:
    def __init__(self, nombre: str, cantidad_paginas: int):
        self.nombre = nombre
        self.cantidad_paginas = cantidad_paginas


# -- Listas y colecciones --

from typing import List  # , Tuple, Set, etc...


class EstanteLibro:
    def __init__(self, libros: List[Libro]):
        self.libros = libros

    def __str__(self) -> str:
        return f"EstanteLibro con {len(self.libros)} libros."


# El beneficio principal es que ahora se te avisara cuando le pases el tipo incorrecto...

libro = Libro(
    "Harry Potter", "352"
)  # Sugiere que esto es incorrecto si tienes una herramienta que analiza tu código (e.g. PyCharm o Pylint)
estante = EstanteLibro(libro)  # También sugiere error aqui 
# Type hinting es eso: un hint (una pista, un indicio). No detiene la ejecución del código... pero puede salvarte la vida a veces!
# Type hinting en Python 3.5+
# El beneficio principal es que ahora se te avisara cuando le pases el tipo incorrecto...

libro = Libro(
    "Harry Potter", "352"
)  # Sugiere que esto es incorrecto si tienes una herramienta que analiza tu código (e.g. PyCharm o Pylint)
estante = EstanteLibro(libro)  # También sugiere error aqui 
# Type hinting es eso: un hint (una pista, un indicio). No detiene la ejecución del código... pero puede salvarte la vida a veces!


# -- Hinting del objecto actual --


class Libro:
    TYPES = ("tapa_dura", "tapa_blanda")

    def __init__(self, name: str, tipo_libro: str, peso: int):
        self.nombre = name
        self.tipo_libro = tipo_libro
        self.peso = peso

    def __repr__(self) -> str:
        return f"<Libro {self.nombre}, {self.tipo_libro}, pesando {self.peso}g>"

    @classmethod
    def tapa_dura(cls, nombre: str, peso: int) -> "Libro":
        return cls(nombre, cls.TYPES[0], peso + 100)

    @classmethod
    def tapa_blanda(cls, name: str, peso: int) -> "Libro":
        return cls(name, cls.TYPES[1], peso)
# INTRODUCCION

THE END

Present Syntax Highlighted Code

<section>
  <h2>Tabular Tables</h2>
  <table>
    <thead>
      <tr>
        <th>Item</th>
        <th>Value</th>
        <th>Quantity</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Apples</td>
        <td>$1</td>
        <td>7</td>
      </tr>
      <tr>
        <td>Lemonade</td>
        <td>$2</td>
        <td>18</td>
      </tr>
      <tr>
        <td>Hand Sanitizer</td>
        <td>$999</td>
        <td>2</td>
      </tr>
    </tbody>
  </table>
</section>
# PRESENTING CODE
  • Introducción
    • Instalación
    • Variables en Python
    • Cadenas de texto
    • Entrada del usuario
    • Primera app python
    • Listas, tuplas y conjuntos
    • Booleans en Python
    • Sentencia "if"
    • Palabra clave "in"
    • Sentencias "if" con "in"
    • Loops en Python
    • Comprensión de listas en Python
    • Diccionarios
    • De-estructuración de variables
    • Funciones en Python
    • Function arguments y parámetros
    • Funciones con valores de retorno
    • Funciones Lambda
    • Dictionary comprehensions
    • Unpacking arguments
    • Unpacking keyword arguments
    • Programación orientada a objetos en Python
    • @classmethod y @staticmethod
  • Herencia de clases
  • Class composition
  • Type hinting en Python 3.5+
  • Imports en Python
  • Imports relativos en Python
  • Errores in Python
  • Errores personalizados
  • Funciones First-class
  • Simple decorators en Python
  • La sintaxis 'at' para los decorators
  • Decorators en funciones con parámetros
  • Decorators con parameters
  • Mutability en Python
  • Mutable default parameters (y porqué son una mala idea)
  • Tu primera API REST
    • Access the course e-book here
    • Configuración inicial para una app Flask
    • Tu primer endpoint de tu API REST
    • ¿Qué es JSON?
    • Como interactuar y probar tu API REST
    • Como crear tiendas en nuestra API REST
    • Como crear items en cada tienda
    • Como obtener una tienda y sus items
  • Almacenar datos en una base de datos SQL
    • Acerca de y porqué usar SQLAlchemy
    • Como codificar un modelo simple en SQLAlchemy
    • Como escribit relaciones uno a muchos en SQLALchemy
    • Como configurar Flask-SQLAlchemy en tu app Flask
    • Como insertar datos en una tabla usando SQLALchemy
    • Como encontrar modelos en la BD por ID o retornar 404
    • Como actualizar modelos en SQLALchemy
    • Como obtener la lista de todos los modelos
    • Como borrar modelos con SQLAlchemy
  • Relaciones "Mucho-a-mucho" con SQLALchemy
    • Cambios en esta sección
    • Relaciones "uno-a-muchos" entre tiendas y etiquetas
    • Relaciones "mucho-a-mucho" entre tiendas y etiquetas