├── .gitignore ├── Backend ├── FastAPI │ ├── db │ │ ├── client.py │ │ ├── models │ │ │ └── user.py │ │ └── schemas │ │ │ └── user.py │ ├── main.py │ ├── requirements.txt │ ├── routers │ │ ├── basic_auth_users.py │ │ ├── jwt_auth_users.py │ │ ├── products.py │ │ ├── users.py │ │ └── users_db.py │ └── static │ │ └── images │ │ └── python.jpg └── type_hints.py ├── Basic ├── 00_helloworld.py ├── 01_variables.py ├── 02_operators.py ├── 03_strings.py ├── 04_lists.py ├── 05_tuples.py ├── 06_sets.py ├── 07_dicts.py ├── 08_conditionals.py ├── 09_loops.py ├── 10_functions.py ├── 11_classes.py ├── 12_exceptions.py ├── 13_modules.py └── my_module.py ├── Images └── header.jpg ├── Intermediate ├── 00_dates.py ├── 01_list_comprehension.py ├── 02_challenges.py ├── 03_lambdas.py ├── 04_higher_order_functions.py ├── 05_error_types.py ├── 06_file_handling.py ├── 07_regular_expressions.py ├── 08_python_package_manager.py ├── my_file.csv ├── my_file.json ├── my_file.txt └── mypackage │ ├── __init__.py │ └── arithmetics.py ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] -------------------------------------------------------------------------------- /Backend/FastAPI/db/client.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480) 2 | 3 | ### MongoDB client ### 4 | 5 | # Descarga versión community: https://www.mongodb.com/try/download 6 | # Instalación:https://www.mongodb.com/docs/manual/tutorial 7 | # Módulo conexión MongoDB: pip install pymongo 8 | # Ejecución: sudo mongod --dbpath "/path/a/la/base/de/datos/" 9 | # Conexión: mongodb://localhost 10 | 11 | from pymongo import MongoClient 12 | 13 | # Descomentar el db_client local o remoto correspondiente 14 | 15 | # Base de datos local MongoDB 16 | db_client = MongoClient().local 17 | 18 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=25470 19 | 20 | # Base de datos remota MongoDB Atlas (https://mongodb.com) 21 | # db_client = MongoClient( 22 | # "mongodb+srv://:@/?retryWrites=true&w=majority").test 23 | 24 | # Despliegue API en la nube: 25 | # Deta - https://www.deta.sh/ 26 | # Intrucciones - https://fastapi.tiangolo.com/deployment/deta/ 27 | -------------------------------------------------------------------------------- /Backend/FastAPI/db/models/user.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480 2 | 3 | ### User model ### 4 | 5 | from pydantic import BaseModel 6 | from typing import Optional 7 | 8 | 9 | class User(BaseModel): 10 | id: Optional[str] 11 | username: str 12 | email: str 13 | -------------------------------------------------------------------------------- /Backend/FastAPI/db/schemas/user.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo (22/12/2022): https://www.twitch.tv/videos/1686104006 2 | 3 | ### User schema ### 4 | 5 | def user_schema(user) -> dict: 6 | return {"id": str(user["_id"]), 7 | "username": user["username"], 8 | "email": user["email"]} 9 | 10 | 11 | def users_schema(users) -> list: 12 | return [user_schema(user) for user in users] 13 | -------------------------------------------------------------------------------- /Backend/FastAPI/main.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A 2 | 3 | ### Hola Mundo ### 4 | 5 | # Documentación oficial: https://fastapi.tiangolo.com/es/ 6 | 7 | # Instala FastAPI: pip install "fastapi[all]" 8 | 9 | from fastapi import FastAPI 10 | from routers import products, users, basic_auth_users, jwt_auth_users, users_db 11 | from fastapi.staticfiles import StaticFiles 12 | 13 | app = FastAPI() 14 | 15 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475 16 | app.include_router(products.router) 17 | app.include_router(users.router) 18 | 19 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094 20 | app.include_router(basic_auth_users.router) 21 | 22 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=17664 23 | app.include_router(jwt_auth_users.router) 24 | 25 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480 26 | app.include_router(users_db.router) 27 | 28 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=13618 29 | app.mount("/static", StaticFiles(directory="static"), name="static") 30 | 31 | 32 | # Url local: http://127.0.0.1:8000 33 | 34 | 35 | @app.get("/") 36 | async def root(): 37 | return "Hola FastAPI!" 38 | 39 | # Url local: http://127.0.0.1:8000/url 40 | 41 | 42 | @app.get("/url") 43 | async def url(): 44 | return {"url": "https://mouredev.com/python"} 45 | 46 | # Inicia el server: uvicorn main:app --reload 47 | # Detener el server: CTRL+C 48 | 49 | # Documentación con Swagger: http://127.0.0.1:8000/docs 50 | # Documentación con Redocly: http://127.0.0.1:8000/redoc 51 | -------------------------------------------------------------------------------- /Backend/FastAPI/requirements.txt: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=27335 2 | fastapi 3 | python-jose 4 | passlib 5 | bcrypt 6 | pymongo 7 | python-multipart -------------------------------------------------------------------------------- /Backend/FastAPI/routers/basic_auth_users.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=14094 2 | 3 | ### Users API con autorización OAuth2 básica ### 4 | 5 | from fastapi import APIRouter, Depends, HTTPException, status 6 | from pydantic import BaseModel 7 | from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm 8 | 9 | router = APIRouter(prefix="/basicauth", 10 | tags=["basicauth"], 11 | responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}) 12 | 13 | oauth2 = OAuth2PasswordBearer(tokenUrl="login") 14 | 15 | 16 | class User(BaseModel): 17 | username: str 18 | full_name: str 19 | email: str 20 | disabled: bool 21 | 22 | 23 | class UserDB(User): 24 | password: str 25 | 26 | 27 | users_db = { 28 | "mouredev": { 29 | "username": "mouredev", 30 | "full_name": "Brais Moure", 31 | "email": "braismoure@mourede.com", 32 | "disabled": False, 33 | "password": "123456" 34 | }, 35 | "mouredev2": { 36 | "username": "mouredev2", 37 | "full_name": "Brais Moure 2", 38 | "email": "braismoure2@mourede.com", 39 | "disabled": True, 40 | "password": "654321" 41 | } 42 | } 43 | 44 | 45 | def search_user_db(username: str): 46 | if username in users_db: 47 | return UserDB(**users_db[username]) 48 | 49 | 50 | def search_user(username: str): 51 | if username in users_db: 52 | return User(**users_db[username]) 53 | 54 | 55 | async def current_user(token: str = Depends(oauth2)): 56 | user = search_user(token) 57 | if not user: 58 | raise HTTPException( 59 | status_code=status.HTTP_401_UNAUTHORIZED, 60 | detail="Credenciales de autenticación inválidas", 61 | headers={"WWW-Authenticate": "Bearer"}) 62 | 63 | if user.disabled: 64 | raise HTTPException( 65 | status_code=status.HTTP_400_BAD_REQUEST, 66 | detail="Usuario inactivo") 67 | 68 | return user 69 | 70 | 71 | @router.post("/login") 72 | async def login(form: OAuth2PasswordRequestForm = Depends()): 73 | user_db = users_db.get(form.username) 74 | if not user_db: 75 | raise HTTPException( 76 | status_code=status.HTTP_400_BAD_REQUEST, detail="El usuario no es correcto") 77 | 78 | user = search_user_db(form.username) 79 | if not form.password == user.password: 80 | raise HTTPException( 81 | status_code=status.HTTP_400_BAD_REQUEST, detail="La contraseña no es correcta") 82 | 83 | return {"access_token": user.username, "token_type": "bearer"} 84 | 85 | 86 | @router.get("/users/me") 87 | async def me(user: User = Depends(current_user)): 88 | return user 89 | -------------------------------------------------------------------------------- /Backend/FastAPI/routers/jwt_auth_users.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=17664 2 | 3 | ### Users API con autorización OAuth2 JWT ### 4 | 5 | from fastapi import APIRouter, Depends, HTTPException, status 6 | from pydantic import BaseModel 7 | from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm 8 | from jose import jwt, JWTError 9 | from passlib.context import CryptContext 10 | from datetime import datetime, timedelta 11 | 12 | ALGORITHM = "HS256" 13 | ACCESS_TOKEN_DURATION = 1 14 | SECRET = "201d573bd7d1344d3a3bfce1550b69102fd11be3db6d379508b6cccc58ea230b" 15 | 16 | router = APIRouter(prefix="/jwtauth", 17 | tags=["jwtauth"], 18 | responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}) 19 | 20 | oauth2 = OAuth2PasswordBearer(tokenUrl="login") 21 | 22 | crypt = CryptContext(schemes=["bcrypt"]) 23 | 24 | 25 | class User(BaseModel): 26 | username: str 27 | full_name: str 28 | email: str 29 | disabled: bool 30 | 31 | 32 | class UserDB(User): 33 | password: str 34 | 35 | 36 | users_db = { 37 | "mouredev": { 38 | "username": "mouredev", 39 | "full_name": "Brais Moure", 40 | "email": "braismoure@mourede.com", 41 | "disabled": False, 42 | "password": "$2a$12$B2Gq.Dps1WYf2t57eiIKjO4DXC3IUMUXISJF62bSRiFfqMdOI2Xa6" 43 | }, 44 | "mouredev2": { 45 | "username": "mouredev2", 46 | "full_name": "Brais Moure 2", 47 | "email": "braismoure2@mourede.com", 48 | "disabled": True, 49 | "password": "$2a$12$SduE7dE.i3/ygwd0Kol8bOFvEABaoOOlC8JsCSr6wpwB4zl5STU4S" 50 | } 51 | } 52 | 53 | 54 | def search_user_db(username: str): 55 | if username in users_db: 56 | return UserDB(**users_db[username]) 57 | 58 | 59 | def search_user(username: str): 60 | if username in users_db: 61 | return User(**users_db[username]) 62 | 63 | 64 | async def auth_user(token: str = Depends(oauth2)): 65 | 66 | exception = HTTPException( 67 | status_code=status.HTTP_401_UNAUTHORIZED, 68 | detail="Credenciales de autenticación inválidas", 69 | headers={"WWW-Authenticate": "Bearer"}) 70 | 71 | try: 72 | username = jwt.decode(token, SECRET, algorithms=[ALGORITHM]).get("sub") 73 | if username is None: 74 | raise exception 75 | 76 | except JWTError: 77 | raise exception 78 | 79 | return search_user(username) 80 | 81 | 82 | async def current_user(user: User = Depends(auth_user)): 83 | if user.disabled: 84 | raise HTTPException( 85 | status_code=status.HTTP_400_BAD_REQUEST, 86 | detail="Usuario inactivo") 87 | 88 | return user 89 | 90 | 91 | @router.post("/login") 92 | async def login(form: OAuth2PasswordRequestForm = Depends()): 93 | 94 | user_db = users_db.get(form.username) 95 | if not user_db: 96 | raise HTTPException( 97 | status_code=status.HTTP_400_BAD_REQUEST, detail="El usuario no es correcto") 98 | 99 | user = search_user_db(form.username) 100 | 101 | if not crypt.verify(form.password, user.password): 102 | raise HTTPException( 103 | status_code=status.HTTP_400_BAD_REQUEST, detail="La contraseña no es correcta") 104 | 105 | access_token = {"sub": user.username, 106 | "exp": datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_DURATION)} 107 | 108 | return {"access_token": jwt.encode(access_token, SECRET, algorithm=ALGORITHM), "token_type": "bearer"} 109 | 110 | 111 | @router.get("/users/me") 112 | async def me(user: User = Depends(current_user)): 113 | return user 114 | -------------------------------------------------------------------------------- /Backend/FastAPI/routers/products.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=12475 2 | 3 | ### Products API ### 4 | 5 | from fastapi import APIRouter 6 | 7 | router = APIRouter(prefix="/products", 8 | tags=["products"], 9 | responses={404: {"message": "No encontrado"}}) 10 | 11 | products_list = ["Producto 1", "Producto 2", 12 | "Producto 3", "Producto 4", "Producto 5"] 13 | 14 | 15 | @router.get("/") 16 | async def products(): 17 | return products_list 18 | 19 | 20 | @router.get("/{id}") 21 | async def products(id: int): 22 | return products_list[id] 23 | -------------------------------------------------------------------------------- /Backend/FastAPI/routers/users.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=5382 2 | 3 | ### Users API ### 4 | 5 | from fastapi import APIRouter, HTTPException 6 | from pydantic import BaseModel 7 | 8 | # Inicia el server: uvicorn users:app --reload 9 | 10 | router = APIRouter() 11 | 12 | 13 | class User(BaseModel): 14 | id: int 15 | name: str 16 | surname: str 17 | url: str 18 | age: int 19 | 20 | 21 | users_list = [User(id=1, name="Brais", surname="Moure", url="https://moure.dev", age=35), 22 | User(id=2, name="Moure", surname="Dev", 23 | url="https://mouredev.com", age=35), 24 | User(id=3, name="Brais", surname="Dahlberg", url="https://haakon.com", age=33)] 25 | 26 | 27 | @router.get("/usersjson") 28 | async def usersjson(): # Creamos un JSON a mano 29 | return [{"name": "Brais", "surname": "Moure", "url": "https://moure.dev", "age": 35}, 30 | {"name": "Moure", "surname": "Dev", 31 | "url": "https://mouredev.com", "age": 35}, 32 | {"name": "Haakon", "surname": "Dahlberg", "url": "https://haakon.com", "age": 33}] 33 | 34 | 35 | @router.get("/users") 36 | async def users(): 37 | return users_list 38 | 39 | 40 | @router.get("/user/{id}") # Path 41 | async def user(id: int): 42 | return search_user(id) 43 | 44 | 45 | @router.get("/user/") # Query 46 | async def user(id: int): 47 | return search_user(id) 48 | 49 | 50 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=8529 51 | 52 | 53 | @router.post("/user/", response_model=User, status_code=201) 54 | async def user(user: User): 55 | if type(search_user(user.id)) == User: 56 | raise HTTPException(status_code=404, detail="El usuario ya existe") 57 | 58 | users_list.append(user) 59 | return user 60 | 61 | 62 | @router.put("/user/") 63 | async def user(user: User): 64 | 65 | found = False 66 | 67 | for index, saved_user in enumerate(users_list): 68 | if saved_user.id == user.id: 69 | users_list[index] = user 70 | found = True 71 | 72 | if not found: 73 | return {"error": "No se ha actualizado el usuario"} 74 | 75 | return user 76 | 77 | 78 | @router.delete("/user/{id}") 79 | async def user(id: int): 80 | 81 | found = False 82 | 83 | for index, saved_user in enumerate(users_list): 84 | if saved_user.id == id: 85 | del users_list[index] 86 | found = True 87 | 88 | if not found: 89 | return {"error": "No se ha eliminado el usuario"} 90 | 91 | 92 | def search_user(id: int): 93 | users = filter(lambda user: user.id == id, users_list) 94 | try: 95 | return list(users)[0] 96 | except: 97 | return {"error": "No se ha encontrado el usuario"} 98 | -------------------------------------------------------------------------------- /Backend/FastAPI/routers/users_db.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=20480 2 | 3 | ### Users DB API ### 4 | 5 | from fastapi import APIRouter, HTTPException, status 6 | from db.models.user import User 7 | from db.schemas.user import user_schema, users_schema 8 | from db.client import db_client 9 | from bson import ObjectId 10 | 11 | router = APIRouter(prefix="/userdb", 12 | tags=["userdb"], 13 | responses={status.HTTP_404_NOT_FOUND: {"message": "No encontrado"}}) 14 | 15 | 16 | @router.get("/", response_model=list[User]) 17 | async def users(): 18 | return users_schema(db_client.users.find()) 19 | 20 | 21 | @router.get("/{id}") # Path 22 | async def user(id: str): 23 | return search_user("_id", ObjectId(id)) 24 | 25 | 26 | @router.get("/") # Query 27 | async def user(id: str): 28 | return search_user("_id", ObjectId(id)) 29 | 30 | 31 | @router.post("/", response_model=User, status_code=status.HTTP_201_CREATED) 32 | async def user(user: User): 33 | if type(search_user("email", user.email)) == User: 34 | raise HTTPException( 35 | status_code=status.HTTP_404_NOT_FOUND, detail="El usuario ya existe") 36 | 37 | user_dict = dict(user) 38 | del user_dict["id"] 39 | 40 | id = db_client.users.insert_one(user_dict).inserted_id 41 | 42 | new_user = user_schema(db_client.users.find_one({"_id": id})) 43 | 44 | return User(**new_user) 45 | 46 | 47 | @router.put("/", response_model=User) 48 | async def user(user: User): 49 | 50 | user_dict = dict(user) 51 | del user_dict["id"] 52 | 53 | try: 54 | db_client.users.find_one_and_replace( 55 | {"_id": ObjectId(user.id)}, user_dict) 56 | except: 57 | return {"error": "No se ha actualizado el usuario"} 58 | 59 | return search_user("_id", ObjectId(user.id)) 60 | 61 | 62 | @router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT) 63 | async def user(id: str): 64 | 65 | found = db_client.users.find_one_and_delete({"_id": ObjectId(id)}) 66 | 67 | if not found: 68 | return {"error": "No se ha eliminado el usuario"} 69 | 70 | # Helper 71 | 72 | 73 | def search_user(field: str, key): 74 | 75 | try: 76 | user = db_client.users.find_one({field: key}) 77 | return User(**user_schema(user)) 78 | except: 79 | return {"error": "No se ha encontrado el usuario"} 80 | -------------------------------------------------------------------------------- /Backend/FastAPI/static/images/python.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CamiloHCardona/https-github.com-mouredev-Hello-Python/fcfc58b7452edc4364010cd109db6e3628466da3/Backend/FastAPI/static/images/python.jpg -------------------------------------------------------------------------------- /Backend/type_hints.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/_y9qQZXE24A?t=1810 2 | 3 | ### Type Hints ### 4 | 5 | my_string_variable = "My String variable" 6 | print(my_string_variable) 7 | print(type(my_string_variable)) 8 | 9 | my_string_variable = 5 10 | print(my_string_variable) 11 | print(type(my_string_variable)) 12 | 13 | my_typed_variable: str = "My typed String variable" 14 | print(my_typed_variable) 15 | print(type(my_typed_variable)) 16 | 17 | my_typed_variable = 5 18 | print(my_typed_variable) 19 | print(type(my_typed_variable)) 20 | -------------------------------------------------------------------------------- /Basic/00_helloworld.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc 2 | 3 | ### Hola Mundo ### 4 | 5 | # Nuestro hola mundo en Python 6 | print("Hola Python") 7 | print('Hola Python') 8 | 9 | # Esto es un comentario 10 | 11 | """ 12 | Este es un 13 | comentario 14 | en varias líneas 15 | """ 16 | 17 | ''' 18 | Este también es un 19 | comentario 20 | en varias líneas 21 | ''' 22 | 23 | # Cómo consultar el tipo de dato 24 | print(type("Soy un dato str")) # Tipo 'str' 25 | print(type(5)) # Tipo 'int' 26 | print(type(1.5)) # Tipo 'float' 27 | print(type(3 + 1j)) # Tipo 'complex' 28 | print(type(True)) # Tipo 'bool' 29 | print(type(print("Mi cadena de texto"))) # Tipo 'NoneType' 30 | -------------------------------------------------------------------------------- /Basic/01_variables.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=2938 2 | 3 | ### Variables ### 4 | 5 | my_string_variable = "My String variable" 6 | print(my_string_variable) 7 | 8 | my_int_variable = 5 9 | print(my_int_variable) 10 | 11 | my_int_to_str_variable = str(my_int_variable) 12 | print(my_int_to_str_variable) 13 | print(type(my_int_to_str_variable)) 14 | 15 | my_bool_variable = False 16 | print(my_bool_variable) 17 | 18 | # Concatenación de variables en un print 19 | print(my_string_variable, my_int_to_str_variable, my_bool_variable) 20 | print("Este es el valor de:", my_bool_variable) 21 | 22 | # Algunas funciones del sistema 23 | print(len(my_string_variable)) 24 | 25 | # Variables en una sola línea. ¡Cuidado con abusar de esta sintaxis! 26 | name, surname, alias, age = "Brais", "Moure", 'MoureDev', 35 27 | print("Me llamo:", name, surname, ". Mi edad es:", 28 | age, ". Y mi alias es:", alias) 29 | 30 | # Inputs 31 | name = input('¿Cuál es tu nombre? ') 32 | age = input('¿Cuántos años tienes? ') 33 | print(name) 34 | print(age) 35 | 36 | # Cambiamos su tipo 37 | name = 35 38 | age = "Brais" 39 | print(name) 40 | print(age) 41 | 42 | # ¿Forzamos el tipo? 43 | address: str = "Mi dirección" 44 | address = True 45 | address = 5 46 | address = 1.2 47 | print(type(address)) 48 | -------------------------------------------------------------------------------- /Basic/02_operators.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=5665 2 | 3 | ### Operadores Aritméticos ### 4 | 5 | # Operaciones con enteros 6 | print(3 + 4) 7 | print(3 - 4) 8 | print(3 * 4) 9 | print(3 / 4) 10 | print(10 % 3) 11 | print(10 // 3) 12 | print(2 ** 3) 13 | print(2 ** 3 + 3 - 7 / 1 // 4) 14 | 15 | # Operaciones con cadenas de texto 16 | print("Hola " + "Python " + "¿Qué tal?") 17 | print("Hola " + str(5)) 18 | 19 | # Operaciones mixtas 20 | print("Hola " * 5) 21 | print("Hola " * (2 ** 3)) 22 | 23 | my_float = 2.5 * 2 24 | print("Hola " * int(my_float)) 25 | 26 | ### Operadores Comparativos ### 27 | 28 | # Operaciones con enteros 29 | print(3 > 4) 30 | print(3 < 4) 31 | print(3 >= 4) 32 | print(4 <= 4) 33 | print(3 == 4) 34 | print(3 != 4) 35 | 36 | # Operaciones con cadenas de texto 37 | print("Hola" > "Python") 38 | print("Hola" < "Python") 39 | print("aaaa" >= "abaa") # Ordenación alfabética por ASCII 40 | print(len("aaaa") >= len("abaa")) # Cuenta caracteres 41 | print("Hola" <= "Python") 42 | print("Hola" == "Hola") 43 | print("Hola" != "Python") 44 | 45 | ### Operadores Lógicos ### 46 | 47 | # Basada en el Álgebra de Boole https://es.wikipedia.org/wiki/%C3%81lgebra_de_Boole 48 | print(3 > 4 and "Hola" > "Python") 49 | print(3 > 4 or "Hola" > "Python") 50 | print(3 < 4 and "Hola" < "Python") 51 | print(3 < 4 or "Hola" > "Python") 52 | print(3 < 4 or ("Hola" > "Python" and 4 == 4)) 53 | print(not (3 > 4)) 54 | -------------------------------------------------------------------------------- /Basic/03_strings.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=8643 2 | 3 | ### Strings ### 4 | 5 | my_string = "Mi String" 6 | my_other_string = 'Mi otro String' 7 | 8 | print(len(my_string)) 9 | print(len(my_other_string)) 10 | print(my_string + " " + my_other_string) 11 | 12 | my_new_line_string = "Este es un String\ncon salto de línea" 13 | print(my_new_line_string) 14 | 15 | my_tab_string = "\tEste es un String con tabulación" 16 | print(my_tab_string) 17 | 18 | my_scape_string = "\\tEste es un String \\n escapado" 19 | print(my_scape_string) 20 | 21 | # Formateo 22 | 23 | name, surname, age = "Brais", "Moure", 35 24 | print("Mi nombre es {} {} y mi edad es {}".format(name, surname, age)) 25 | print("Mi nombre es %s %s y mi edad es %d" % (name, surname, age)) 26 | print("Mi nombre es " + name + " " + surname + " y mi edad es " + str(age)) 27 | print(f"Mi nombre es {name} {surname} y mi edad es {age}") 28 | 29 | # Desempaqueado de caracteres 30 | 31 | language = "python" 32 | a, b, c, d, e, f = language 33 | print(a) 34 | print(e) 35 | 36 | # División 37 | 38 | language_slice = language[1:3] 39 | print(language_slice) 40 | 41 | language_slice = language[1:] 42 | print(language_slice) 43 | 44 | language_slice = language[-2] 45 | print(language_slice) 46 | 47 | language_slice = language[0:6:2] 48 | print(language_slice) 49 | 50 | # Reverse 51 | 52 | reversed_language = language[::-1] 53 | print(reversed_language) 54 | 55 | # Funciones del lenguaje 56 | 57 | print(language.capitalize()) 58 | print(language.upper()) 59 | print(language.count("t")) 60 | print(language.isnumeric()) 61 | print("1".isnumeric()) 62 | print(language.lower()) 63 | print(language.lower().isupper()) 64 | print(language.startswith("Py")) 65 | print("Py" == "py") # No es lo mismo 66 | -------------------------------------------------------------------------------- /Basic/04_lists.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=10872 2 | 3 | ### Lists ### 4 | 5 | # Definición 6 | 7 | my_list = list() 8 | my_other_list = [] 9 | 10 | print(len(my_list)) 11 | 12 | my_list = [35, 24, 62, 52, 30, 30, 17] 13 | 14 | print(my_list) 15 | print(len(my_list)) 16 | 17 | my_other_list = [35, 1.77, "Brais", "Moure"] 18 | 19 | print(type(my_list)) 20 | print(type(my_other_list)) 21 | 22 | # Acceso a elementos y búsqueda 23 | 24 | print(my_other_list[0]) 25 | print(my_other_list[1]) 26 | print(my_other_list[-1]) 27 | print(my_other_list[-4]) 28 | print(my_list.count(30)) 29 | # print(my_other_list[4]) IndexError 30 | # print(my_other_list[-5]) IndexError 31 | 32 | print(my_other_list.index("Brais")) 33 | 34 | age, height, name, surname = my_other_list 35 | print(name) 36 | 37 | name, height, age, surname = my_other_list[2], my_other_list[1], my_other_list[0], my_other_list[3] 38 | print(age) 39 | 40 | # Concatenación 41 | 42 | print(my_list + my_other_list) 43 | #print(my_list - my_other_list) 44 | 45 | # Creación, inserción, actualización y eliminación 46 | 47 | my_other_list.append("MoureDev") 48 | print(my_other_list) 49 | 50 | my_other_list.insert(1, "Rojo") 51 | print(my_other_list) 52 | 53 | my_other_list[1] = "Azul" 54 | print(my_other_list) 55 | 56 | my_other_list.remove("Azul") 57 | print(my_other_list) 58 | 59 | my_list.remove(30) 60 | print(my_list) 61 | 62 | print(my_list.pop()) 63 | print(my_list) 64 | 65 | my_pop_element = my_list.pop(2) 66 | print(my_pop_element) 67 | print(my_list) 68 | 69 | del my_list[2] 70 | print(my_list) 71 | 72 | # Operaciones con listas 73 | 74 | my_new_list = my_list.copy() 75 | 76 | my_list.clear() 77 | print(my_list) 78 | print(my_new_list) 79 | 80 | my_new_list.reverse() 81 | print(my_new_list) 82 | 83 | my_new_list.sort() 84 | print(my_new_list) 85 | 86 | # Sublistas 87 | 88 | print(my_new_list[1:3]) 89 | 90 | # Cambio de tipo 91 | 92 | my_list = "Hola Python" 93 | print(my_list) 94 | print(type(my_list)) 95 | -------------------------------------------------------------------------------- /Basic/05_tuples.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=14711 2 | 3 | ### Tuples ### 4 | 5 | # Definición 6 | 7 | my_tuple = tuple() 8 | my_other_tuple = () 9 | 10 | my_tuple = (35, 1.77, "Brais", "Moure", "Brais") 11 | my_other_tuple = (35, 60, 30) 12 | 13 | print(my_tuple) 14 | print(type(my_tuple)) 15 | 16 | # Acceso a elementos y búsqueda 17 | 18 | print(my_tuple[0]) 19 | print(my_tuple[-1]) 20 | # print(my_tuple[4]) IndexError 21 | # print(my_tuple[-6]) IndexError 22 | 23 | print(my_tuple.count("Brais")) 24 | print(my_tuple.index("Moure")) 25 | print(my_tuple.index("Brais")) 26 | 27 | # my_tuple[1] = 1.80 'tuple' object does not support item assignment 28 | 29 | # Concatenación 30 | 31 | my_sum_tuple = my_tuple + my_other_tuple 32 | print(my_sum_tuple) 33 | 34 | # Subtuplas 35 | 36 | print(my_sum_tuple[3:6]) 37 | 38 | # Tupla mutable con conversión a lista 39 | 40 | my_tuple = list(my_tuple) 41 | print(type(my_tuple)) 42 | 43 | my_tuple[4] = "MoureDev" 44 | my_tuple.insert(1, "Azul") 45 | my_tuple = tuple(my_tuple) 46 | print(my_tuple) 47 | print(type(my_tuple)) 48 | 49 | # Eliminación 50 | 51 | # del my_tuple[2] TypeError: 'tuple' object doesn't support item deletion 52 | 53 | del my_tuple 54 | # print(my_tuple) NameError: name 'my_tuple' is not defined 55 | -------------------------------------------------------------------------------- /Basic/06_sets.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=16335 2 | 3 | ### Sets ### 4 | 5 | # Definición 6 | 7 | my_set = set() 8 | my_other_set = {} 9 | 10 | print(type(my_set)) 11 | print(type(my_other_set)) # Inicialmente es un diccionario 12 | 13 | my_other_set = {"Brais", "Moure", 35} 14 | print(type(my_other_set)) 15 | 16 | print(len(my_other_set)) 17 | 18 | # Inserción 19 | 20 | my_other_set.add("MoureDev") 21 | 22 | print(my_other_set) # Un set no es una estructura ordenada 23 | 24 | my_other_set.add("MoureDev") # Un set no admite repetidos 25 | 26 | print(my_other_set) 27 | 28 | # Búsqueda 29 | 30 | print("Moure" in my_other_set) 31 | print("Mouri" in my_other_set) 32 | 33 | # Eliminación 34 | 35 | my_other_set.remove("Moure") 36 | print(my_other_set) 37 | 38 | my_other_set.clear() 39 | print(len(my_other_set)) 40 | 41 | del my_other_set 42 | # print(my_other_set) NameError: name 'my_other_set' is not defined 43 | 44 | # Transformación 45 | 46 | my_set = {"Brais", "Moure", 35} 47 | my_list = list(my_set) 48 | print(my_list) 49 | print(my_list[0]) 50 | 51 | my_other_set = {"Kotlin", "Swift", "Python"} 52 | 53 | # Otras operaciones 54 | 55 | my_new_set = my_set.union(my_other_set) 56 | print(my_new_set.union(my_new_set).union(my_set).union({"JavaScript", "C#"})) 57 | print(my_new_set.difference(my_set)) 58 | -------------------------------------------------------------------------------- /Basic/07_dicts.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc 2 | 3 | ### Dictionaries ### 4 | 5 | # Definición 6 | 7 | my_dict = dict() 8 | my_other_dict = {} 9 | 10 | print(type(my_dict)) 11 | print(type(my_other_dict)) 12 | 13 | my_other_dict = {"Nombre": "Brais", 14 | "Apellido": "Moure", "Edad": 35, 1: "Python"} 15 | 16 | my_dict = { 17 | "Nombre": "Brais", 18 | "Apellido": "Moure", 19 | "Edad": 35, 20 | "Lenguajes": {"Python", "Swift", "Kotlin"}, 21 | 1: 1.77 22 | } 23 | 24 | print(my_other_dict) 25 | print(my_dict) 26 | 27 | print(len(my_other_dict)) 28 | print(len(my_dict)) 29 | 30 | # Búsqueda 31 | 32 | print(my_dict[1]) 33 | print(my_dict["Nombre"]) 34 | 35 | print("Moure" in my_dict) 36 | print("Apellido" in my_dict) 37 | 38 | # Inserción 39 | 40 | my_dict["Calle"] = "Calle MoureDev" 41 | print(my_dict) 42 | 43 | # Actualización 44 | 45 | my_dict["Nombre"] = "Pedro" 46 | print(my_dict["Nombre"]) 47 | 48 | # Eliminación 49 | 50 | del my_dict["Calle"] 51 | print(my_dict) 52 | 53 | # Otras operaciones 54 | 55 | print(my_dict.items()) 56 | print(my_dict.keys()) 57 | print(my_dict.values()) 58 | 59 | my_list = ["Nombre", 1, "Piso"] 60 | 61 | my_new_dict = dict.fromkeys((my_list)) 62 | print(my_new_dict) 63 | my_new_dict = dict.fromkeys(("Nombre", 1, "Piso")) 64 | print((my_new_dict)) 65 | my_new_dict = dict.fromkeys(my_dict) 66 | print((my_new_dict)) 67 | my_new_dict = dict.fromkeys(my_dict, "MoureDev") 68 | print((my_new_dict)) 69 | 70 | my_values = my_new_dict.values() 71 | print(type(my_values)) 72 | 73 | print(my_new_dict.values()) 74 | print(list(dict.fromkeys(list(my_new_dict.values())).keys())) 75 | print(tuple(my_new_dict)) 76 | print(set(my_new_dict)) 77 | -------------------------------------------------------------------------------- /Basic/08_conditionals.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=21442 2 | 3 | ### Conditionals ### 4 | 5 | # if 6 | 7 | my_condition = False 8 | 9 | if my_condition: # Es lo mismo que if my_condition == True: 10 | print("Se ejecuta la condición del if") 11 | 12 | my_condition = 5 * 5 13 | 14 | if my_condition == 10: 15 | print("Se ejecuta la condición del segundo if") 16 | 17 | # if, elif, else 18 | 19 | if my_condition > 10 and my_condition < 20: 20 | print("Es mayor que 10 y menor que 20") 21 | elif my_condition == 25: 22 | print("Es igual a 25") 23 | else: 24 | print("Es menor o igual que 10 o mayor o igual que 20 o distinto de 25") 25 | 26 | print("La ejecución continúa") 27 | 28 | # Condicional con ispección de valor 29 | 30 | my_string = "" 31 | 32 | if not my_string: 33 | print("Mi cadena de texto es vacía") 34 | 35 | if my_string == "Mi cadena de textoooooo": 36 | print("Estas cadenas de texto coinciden") 37 | -------------------------------------------------------------------------------- /Basic/09_loops.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=23822 2 | 3 | ### Loops ### 4 | 5 | # While 6 | 7 | my_condition = 0 8 | 9 | while my_condition < 10: 10 | print(my_condition) 11 | my_condition += 2 12 | else: # Es opcional 13 | print("Mi condición es mayor o igual que 10") 14 | 15 | print("La ejecución continúa") 16 | 17 | while my_condition < 20: 18 | my_condition += 1 19 | if my_condition == 15: 20 | print("Se detiene la ejecución") 21 | break 22 | print(my_condition) 23 | 24 | print("La ejecución continúa") 25 | 26 | # For 27 | 28 | my_list = [35, 24, 62, 52, 30, 30, 17] 29 | 30 | for element in my_list: 31 | print(element) 32 | 33 | my_tuple = (35, 1.77, "Brais", "Moure", "Brais") 34 | 35 | for element in my_tuple: 36 | print(element) 37 | 38 | my_set = {"Brais", "Moure", 35} 39 | 40 | for element in my_set: 41 | print(element) 42 | 43 | my_dict = {"Nombre": "Brais", "Apellido": "Moure", "Edad": 35, 1: "Python"} 44 | 45 | for element in my_dict: 46 | print(element) 47 | if element == "Edad": 48 | break 49 | else: 50 | print("El bluce for para diccionario ha finalizado") 51 | 52 | print("La ejecución continúa") 53 | 54 | for element in my_dict: 55 | print(element) 56 | if element == "Edad": 57 | continue 58 | print("Se ejecuta") 59 | else: 60 | print("El bluce for para diccionario ha finalizado") 61 | -------------------------------------------------------------------------------- /Basic/10_functions.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=26619 2 | 3 | ### Functions ### 4 | 5 | # Definición 6 | 7 | def my_function(): 8 | print("Esto es una función") 9 | 10 | 11 | my_function() 12 | my_function() 13 | my_function() 14 | 15 | # Función con parámetros de entrada/argumentos 16 | 17 | 18 | def sum_two_values(first_value: int, second_value): 19 | print(first_value + second_value) 20 | 21 | 22 | sum_two_values(5, 7) 23 | sum_two_values(54754, 71231) 24 | sum_two_values("5", "7") 25 | sum_two_values(1.4, 5.2) 26 | 27 | # Función con parámetros de entrada/argumentos y retorno 28 | 29 | 30 | def sum_two_values_with_return(first_value, second_value): 31 | my_sum = first_value + second_value 32 | return my_sum 33 | 34 | 35 | my_result = sum_two_values(1.4, 5.2) 36 | print(my_result) 37 | 38 | my_result = sum_two_values_with_return(10, 5) 39 | print(my_result) 40 | 41 | # Función con parámetros de entrada/argumentos por clave 42 | 43 | 44 | def print_name(name, surname): 45 | print(f"{name} {surname}") 46 | 47 | 48 | print_name(surname="Moure", name="Brais") 49 | 50 | # Función con parámetros de entrada/argumentos por defecto 51 | 52 | 53 | def print_name_with_default(name, surname, alias="Sin alias"): 54 | print(f"{name} {surname} {alias}") 55 | 56 | 57 | print_name_with_default("Brais", "Moure") 58 | print_name_with_default("Brais", "Moure", "MoureDev") 59 | 60 | # Función con parámetros de entrada/argumentos arbitrarios 61 | 62 | 63 | def print_upper_texts(*texts): 64 | print(type(texts)) 65 | for text in texts: 66 | print(text.upper()) 67 | 68 | 69 | print_upper_texts("Hola", "Python", "MoureDev") 70 | print_upper_texts("Hola") 71 | -------------------------------------------------------------------------------- /Basic/11_classes.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=29327 2 | 3 | ### Classes ### 4 | 5 | # Definición 6 | 7 | class MyEmptyPerson: 8 | pass # Para poder dejar la clase vacía 9 | 10 | 11 | print(MyEmptyPerson) 12 | print(MyEmptyPerson()) 13 | 14 | # Clase con constructor, funciones y popiedades privadas y públicas 15 | 16 | 17 | class Person: 18 | def __init__(self, name, surname, alias="Sin alias"): 19 | self.full_name = f"{name} {surname} ({alias})" # Propiedad pública 20 | self.__name = name # Propiedad privada 21 | 22 | def get_name(self): 23 | return self.__name 24 | 25 | def walk(self): 26 | print(f"{self.full_name} está caminando") 27 | 28 | 29 | my_person = Person("Brais", "Moure") 30 | print(my_person.full_name) 31 | print(my_person.get_name()) 32 | my_person.walk() 33 | 34 | my_other_person = Person("Brais", "Moure", "MoureDev") 35 | print(my_other_person.full_name) 36 | my_other_person.walk() 37 | my_other_person.full_name = "Héctor de León (El loco de los perros)" 38 | print(my_other_person.full_name) 39 | 40 | my_other_person.full_name = 666 41 | print(my_other_person.full_name) 42 | -------------------------------------------------------------------------------- /Basic/12_exceptions.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=32030 2 | 3 | ### Exception Handling ### 4 | 5 | numberOne = 5 6 | numberTwo = 1 7 | numberTwo = "1" 8 | 9 | # Excepción base: try except 10 | 11 | try: 12 | print(numberOne + numberTwo) 13 | print("No se ha producido un error") 14 | except: 15 | # Se ejecuta si se produce una excepción 16 | print("Se ha producido un error") 17 | 18 | # Flujo completo de una excepción: try except else finally 19 | 20 | try: 21 | print(numberOne + numberTwo) 22 | print("No se ha producido un error") 23 | except: 24 | print("Se ha producido un error") 25 | else: # Opcional 26 | # Se ejecuta si no se produce una excepción 27 | print("La ejecución continúa correctamente") 28 | finally: # Opcional 29 | # Se ejecuta siempre 30 | print("La ejecución continúa") 31 | 32 | # Excepciones por tipo 33 | 34 | try: 35 | print(numberOne + numberTwo) 36 | print("No se ha producido un error") 37 | except ValueError: 38 | print("Se ha producido un ValueError") 39 | except TypeError: 40 | print("Se ha producido un TypeError") 41 | 42 | # Captura de la información de la excepción 43 | 44 | try: 45 | print(numberOne + numberTwo) 46 | print("No se ha producido un error") 47 | except ValueError as error: 48 | print(error) 49 | except Exception as my_random_error_name: 50 | print(my_random_error_name) 51 | -------------------------------------------------------------------------------- /Basic/13_modules.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=34583 2 | 3 | ### Modules ### 4 | 5 | from math import pi as PI_VALUE 6 | import math 7 | from my_module import sumValue, printValue 8 | import my_module 9 | 10 | my_module.sumValue(5, 3, 1) 11 | my_module.printValue("Hola Python!") 12 | 13 | 14 | sumValue(5, 3, 1) 15 | printValue("Hola python") 16 | 17 | 18 | print(math.pi) 19 | print(math.pow(2, 8)) 20 | 21 | 22 | print(PI_VALUE) 23 | -------------------------------------------------------------------------------- /Basic/my_module.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/Kp4Mvapo5kc?t=34583 2 | 3 | ### Módulo para pruebas ### 4 | 5 | def sumValue(numberOne, numberTwo, numberThree): 6 | print(numberOne + numberTwo + numberThree) 7 | 8 | 9 | def printValue(value): 10 | print(value) 11 | -------------------------------------------------------------------------------- /Images/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CamiloHCardona/https-github.com-mouredev-Hello-Python/fcfc58b7452edc4364010cd109db6e3628466da3/Images/header.jpg -------------------------------------------------------------------------------- /Intermediate/00_dates.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU 2 | 3 | ### Dates ### 4 | 5 | # Date time 6 | 7 | from datetime import timedelta 8 | from datetime import date 9 | from datetime import time 10 | from datetime import datetime 11 | 12 | now = datetime.now() 13 | 14 | 15 | def print_date(date): 16 | print(date.year) 17 | print(date.month) 18 | print(date.day) 19 | print(date.hour) 20 | print(date.minute) 21 | print(date.second) 22 | print(date.timestamp()) 23 | 24 | 25 | print_date(now) 26 | 27 | year_2023 = datetime(2023, 1, 1) 28 | 29 | print_date(year_2023) 30 | 31 | # Time 32 | 33 | 34 | current_time = time(21, 6, 0) 35 | 36 | print(current_time.hour) 37 | print(current_time.minute) 38 | print(current_time.second) 39 | 40 | # Date 41 | 42 | 43 | current_date = date.today() 44 | 45 | print(current_date.year) 46 | print(current_date.month) 47 | print(current_date.day) 48 | 49 | current_date = date(2022, 10, 6) 50 | 51 | print(current_date.year) 52 | print(current_date.month) 53 | print(current_date.day) 54 | 55 | current_date = date(current_date.year, 56 | current_date.month + 1, current_date.day) 57 | 58 | print(current_date.month) 59 | 60 | # Operaciones con fechas 61 | 62 | diff = year_2023 - now 63 | print(diff) 64 | 65 | diff = year_2023.date() - current_date 66 | print(diff) 67 | 68 | # Timedelta 69 | 70 | 71 | start_timedelta = timedelta(200, 100, 100, weeks=10) 72 | end_timedelta = timedelta(300, 100, 100, weeks=13) 73 | 74 | print(end_timedelta - start_timedelta) 75 | print(end_timedelta + start_timedelta) 76 | -------------------------------------------------------------------------------- /Intermediate/01_list_comprehension.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=3239 2 | 3 | ### List Comprehension ### 4 | 5 | my_original_list = [0, 1, 2, 3, 4, 5, 6, 7] 6 | print(my_original_list) 7 | 8 | my_range = range(8) 9 | print(list(my_range)) 10 | 11 | # Definición 12 | 13 | my_list = [i + 1 for i in range(8)] 14 | print(my_list) 15 | 16 | my_list = [i * 2 for i in range(8)] 17 | print(my_list) 18 | 19 | my_list = [i * i for i in range(8)] 20 | print(my_list) 21 | 22 | 23 | def sum_five(number): 24 | return number + 5 25 | 26 | 27 | my_list = [sum_five(i) for i in range(8)] 28 | print(my_list) 29 | -------------------------------------------------------------------------------- /Intermediate/02_challenges.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=4142 2 | 3 | ### Challenges ### 4 | 5 | """ 6 | EL FAMOSO "FIZZ BUZZ”: 7 | Escribe un programa que muestre por consola (con un print) los 8 | números de 1 a 100 (ambos incluidos y con un salto de línea entre 9 | cada impresión), sustituyendo los siguientes: 10 | - Múltiplos de 3 por la palabra "fizz". 11 | - Múltiplos de 5 por la palabra "buzz". 12 | - Múltiplos de 3 y de 5 a la vez por la palabra "fizzbuzz". 13 | """ 14 | 15 | 16 | def fizzbuzz(): 17 | for index in range(1, 101): 18 | if index % 3 == 0 and index % 5 == 0: 19 | print("fizzbuz") 20 | elif index % 3 == 0: 21 | print("fizz") 22 | elif index % 5 == 0: 23 | print("buzz") 24 | else: 25 | print(index) 26 | 27 | 28 | fizzbuzz() 29 | 30 | """ 31 | ¿ES UN ANAGRAMA? 32 | Escribe una función que reciba dos palabras (String) y retorne 33 | verdadero o falso (Bool) según sean o no anagramas. 34 | - Un Anagrama consiste en formar una palabra reordenando TODAS 35 | las letras de otra palabra inicial. 36 | - NO hace falta comprobar que ambas palabras existan. 37 | - Dos palabras exactamente iguales no son anagrama. 38 | """ 39 | 40 | 41 | def is_anagram(word_one, word_two): 42 | if word_one.lower() == word_two.lower(): 43 | return False 44 | return sorted(word_one.lower()) == sorted(word_two.lower()) 45 | 46 | 47 | print(is_anagram("Amor", "Roma")) 48 | 49 | """ 50 | LA SUCESIÓN DE FIBONACCI 51 | Escribe un programa que imprima los 50 primeros números de la sucesión 52 | de Fibonacci empezando en 0. 53 | - La serie Fibonacci se compone por una sucesión de números en 54 | la que el siguiente siempre es la suma de los dos anteriores. 55 | 0, 1, 1, 2, 3, 5, 8, 13... 56 | """ 57 | 58 | 59 | def fibonacci(): 60 | 61 | prev = 0 62 | next = 1 63 | 64 | for index in range(0, 50): 65 | print(prev) 66 | fib = prev + next 67 | prev = next 68 | next = fib 69 | 70 | 71 | fibonacci() 72 | 73 | """ 74 | ¿ES UN NÚMERO PRIMO? 75 | Escribe un programa que se encargue de comprobar si un número es o no primo. 76 | Hecho esto, imprime los números primos entre 1 y 100. 77 | """ 78 | 79 | 80 | def is_prime(): 81 | 82 | for number in range(1, 101): 83 | 84 | if number >= 2: 85 | 86 | is_divisible = False 87 | 88 | for index in range(2, number): 89 | if number % index == 0: 90 | is_divisible = True 91 | break 92 | 93 | if not is_divisible: 94 | print(number) 95 | 96 | 97 | is_prime() 98 | 99 | """ 100 | INVIRTIENDO CADENAS 101 | Crea un programa que invierta el orden de una cadena de texto 102 | sin usar funciones propias del lenguaje que lo hagan de forma automática. 103 | - Si le pasamos "Hola mundo" nos retornaría "odnum aloH" 104 | """ 105 | 106 | 107 | def reverse(text): 108 | text_len = len(text) 109 | reversed_text = "" 110 | for index in range(0, text_len): 111 | reversed_text += text[text_len - index - 1] 112 | return reversed_text 113 | 114 | 115 | print(reverse("Hola mundo")) 116 | -------------------------------------------------------------------------------- /Intermediate/03_lambdas.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=9145 2 | 3 | ### Lambdas ### 4 | 5 | def sum_two_values( 6 | first_value, second_value): return first_value + second_value 7 | 8 | 9 | print(sum_two_values(2, 4)) 10 | 11 | 12 | def multiply_values( 13 | first_value, second_value): return first_value * second_value - 3 14 | 15 | 16 | print(multiply_values(2, 4)) 17 | 18 | 19 | def sum_three_values(value): 20 | return lambda first_value, second_value: first_value + second_value + value 21 | 22 | 23 | print(sum_three_values(5)(2, 4)) 24 | -------------------------------------------------------------------------------- /Intermediate/04_higher_order_functions.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=10172 2 | 3 | ### Higher Order Functions ### 4 | 5 | from functools import reduce 6 | 7 | 8 | def sum_one(value): 9 | return value + 1 10 | 11 | 12 | def sum_five(value): 13 | return value + 5 14 | 15 | 16 | def sum_two_values_and_add_value(first_value, second_value, f_sum): 17 | return f_sum(first_value + second_value) 18 | 19 | 20 | print(sum_two_values_and_add_value(5, 2, sum_one)) 21 | print(sum_two_values_and_add_value(5, 2, sum_five)) 22 | 23 | ### Closures ### 24 | 25 | 26 | def sum_ten(original_value): 27 | def add(value): 28 | return value + 10 + original_value 29 | return add 30 | 31 | 32 | add_closure = sum_ten(1) 33 | print(add_closure(5)) 34 | print((sum_ten(5))(1)) 35 | 36 | ### Built-in Higher Order Functions ### 37 | 38 | numbers = [2, 5, 10, 21, 3, 30] 39 | 40 | # Map 41 | 42 | 43 | def multiply_two(number): 44 | return number * 2 45 | 46 | 47 | print(list(map(multiply_two, numbers))) 48 | print(list(map(lambda number: number * 2, numbers))) 49 | 50 | # Filter 51 | 52 | 53 | def filter_greater_than_ten(number): 54 | if number > 10: 55 | return True 56 | return False 57 | 58 | 59 | print(list(filter(filter_greater_than_ten, numbers))) 60 | print(list(filter(lambda number: number > 10, numbers))) 61 | 62 | # Reduce 63 | 64 | 65 | def sum_two_values(first_value, second_value): 66 | return first_value + second_value 67 | 68 | 69 | print(reduce(sum_two_values, numbers)) 70 | -------------------------------------------------------------------------------- /Intermediate/05_error_types.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=12721 2 | 3 | ### Error Types ### 4 | 5 | # SyntaxError 6 | # print "¡Hola comunidad!" # Descomentar para Error 7 | from math import pi 8 | import math 9 | print("¡Hola comunidad!") 10 | 11 | # NameError 12 | language = "Spanish" # Comentar para Error 13 | print(language) 14 | 15 | # IndexError 16 | my_list = ["Python", "Swift", "Kotlin", "Dart", "JavaScript"] 17 | print(my_list[0]) 18 | print(my_list[4]) 19 | print(my_list[-1]) 20 | # print(my_list[5]) # Descomentar para Error 21 | 22 | # ModuleNotFoundError 23 | # import maths # Descomentar para Error 24 | 25 | # AttributeError 26 | # print(math.PI) # Descomentar para Error 27 | print(math.pi) 28 | 29 | # KeyError 30 | my_dict = {"Nombre": "Brais", "Apellido": "Moure", "Edad": 35, 1: "Python"} 31 | print(my_dict["Edad"]) 32 | # print(my_dict["Apelido"]) # Descomentar para Error 33 | print(my_dict["Apellido"]) 34 | 35 | # TypeError 36 | # print(my_list["0"]) # Descomentar para Error 37 | print(my_list[0]) 38 | print(my_list[False]) 39 | 40 | # ImportError 41 | # from math import PI # Descomentar para Error 42 | print(pi) 43 | 44 | # ValueError 45 | #my_int = int("10 Años") 46 | my_int = int("10") # Descomentar para Error 47 | print(type(my_int)) 48 | 49 | # ZeroDivisionError 50 | # print(4/0) # Descomentar para Error 51 | print(4/2) 52 | -------------------------------------------------------------------------------- /Intermediate/06_file_handling.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=15524 2 | 3 | ### File Handling ### 4 | 5 | import xml 6 | import csv 7 | import json 8 | import os 9 | 10 | # .txt file 11 | 12 | # Leer, escribir y sobrescribir si ya existe 13 | txt_file = open("Intermediate/my_file.txt", "w+") 14 | 15 | txt_file.write( 16 | "Mi nombre es Brais\nMi apellido es Moure\n35 años\nY mi lenguaje preferido es Python") 17 | 18 | # print(txt_file.read()) 19 | print(txt_file.read(10)) 20 | print(txt_file.readline()) 21 | print(txt_file.readline()) 22 | for line in txt_file.readlines(): 23 | print(line) 24 | 25 | txt_file.write("\nAunque también me gusta Kotlin") 26 | print(txt_file.readline()) 27 | 28 | txt_file.close() 29 | 30 | with open("Intermediate/my_file.txt", "a") as my_other_file: 31 | my_other_file.write("\nY Swift") 32 | 33 | # os.remove("Intermediate/my_file.txt") 34 | 35 | # Clase en vídeo (03/11/22): https://www.twitch.tv/videos/1642512950 36 | 37 | # .json file 38 | 39 | 40 | json_file = open("Intermediate/my_file.json", "w+") 41 | 42 | json_test = { 43 | "name": "Brais", 44 | "surname": "Moure", 45 | "age": 35, 46 | "languages": ["Python", "Swift", "Kotlin"], 47 | "website": "https://moure.dev"} 48 | 49 | json.dump(json_test, json_file, indent=2) 50 | 51 | json_file.close() 52 | 53 | with open("Intermediate/my_file.json") as my_other_file: 54 | for line in my_other_file.readlines(): 55 | print(line) 56 | 57 | json_dict = json.load(open("Intermediate/my_file.json")) 58 | print(json_dict) 59 | print(type(json_dict)) 60 | print(json_dict["name"]) 61 | 62 | # .csv file 63 | 64 | 65 | csv_file = open("Intermediate/my_file.csv", "w+") 66 | 67 | csv_writer = csv.writer(csv_file) 68 | csv_writer.writerow(["name", "surname", "age", "language", "website"]) 69 | csv_writer.writerow(["Brais", "Moure", 35, "Python", "https://moure.dev"]) 70 | csv_writer.writerow(["Roswell", "", 2, "COBOL", ""]) 71 | 72 | csv_file.close() 73 | 74 | with open("Intermediate/my_file.csv") as my_other_file: 75 | for line in my_other_file.readlines(): 76 | print(line) 77 | 78 | # .xlsx file 79 | # import xlrd # Debe instalarse el módulo 80 | 81 | # .xml file 82 | 83 | # ¿Te atreves a practicar cómo trabajar con este tipo de ficheros? 84 | -------------------------------------------------------------------------------- /Intermediate/07_regular_expressions.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=19762 2 | 3 | ### Regular Expressions ### 4 | 5 | import re 6 | 7 | # match 8 | 9 | my_string = "Esta es la lección número 7: Lección llamada Expresiones Regulares" 10 | my_other_string = "Esta no es la lección número 6: Manejo de ficheros" 11 | 12 | match = re.match("Esta es la lección", my_string, re.I) 13 | print(match) 14 | start, end = match.span() 15 | print(my_string[start:end]) 16 | 17 | match = re.match("Esta no es la lección", my_other_string) 18 | # if not(match == None): # Otra forma de comprobar el None 19 | # if match != None: # Otra forma de comprobar el None 20 | if match is not None: 21 | print(match) 22 | start, end = match.span() 23 | print(my_other_string[start:end]) 24 | 25 | print(re.match("Expresiones Regulares", my_string)) 26 | 27 | # search 28 | 29 | search = re.search("lección", my_string, re.I) 30 | print(search) 31 | start, end = search.span() 32 | print(my_string[start:end]) 33 | 34 | # findall 35 | 36 | findall = re.findall("lección", my_string, re.I) 37 | print(findall) 38 | 39 | # split 40 | 41 | print(re.split(":", my_string)) 42 | 43 | # sub 44 | 45 | print(re.sub("[l|L]ección", "LECCIÓN", my_string)) 46 | print(re.sub("Expresiones Regulares", "RegEx", my_string)) 47 | 48 | # Clase en vídeo (09/11/22): https://www.twitch.tv/videos/1648023317 49 | 50 | ### Regular Expressions Patterns ### 51 | 52 | # Para aprender y validar expresiones regulares: https://regex101.com 53 | 54 | pattern = r"[lL]ección" 55 | print(re.findall(pattern, my_string)) 56 | 57 | pattern = r"[lL]ección|Expresiones" 58 | print(re.findall(pattern, my_string)) 59 | 60 | pattern = r"[0-9]" 61 | print(re.findall(pattern, my_string)) 62 | print(re.search(pattern, my_string)) 63 | 64 | pattern = r"\d" 65 | print(re.findall(pattern, my_string)) 66 | 67 | pattern = r"\D" 68 | print(re.findall(pattern, my_string)) 69 | 70 | pattern = r"[l].*" 71 | print(re.findall(pattern, my_string)) 72 | 73 | email = "mouredev@mouredev.com" 74 | pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z-.]+$" 75 | print(re.match(pattern, email)) 76 | print(re.search(pattern, email)) 77 | print(re.findall(pattern, email)) 78 | 79 | email = "mouredev@mouredev.com.mx" 80 | print(re.findall(pattern, email)) 81 | -------------------------------------------------------------------------------- /Intermediate/08_python_package_manager.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=24010 2 | 3 | ### Python Package Manager ### 4 | 5 | # PIP https://pypi.org 6 | 7 | # pip install pip 8 | # pip --version 9 | 10 | # pip install numpy 11 | import pandas 12 | from mypackage import arithmetics 13 | import requests 14 | import numpy 15 | 16 | print(numpy.version.version) 17 | 18 | numpy_array = numpy.array([35, 24, 62, 52, 30, 30, 17]) 19 | print(type(numpy_array)) 20 | 21 | print(numpy_array * 2) 22 | 23 | # pip install pandas 24 | 25 | # pip list 26 | # pip uninstall pandas 27 | # pip show numpy 28 | 29 | # pip install requests 30 | 31 | response = requests.get("https://pokeapi.co/api/v2/pokemon?limit=151") 32 | print(response) 33 | print(response.status_code) 34 | print(response.json()) 35 | 36 | # Arithmetics Package 37 | 38 | 39 | print(arithmetics.sum_two_values(1, 4)) 40 | -------------------------------------------------------------------------------- /Intermediate/my_file.csv: -------------------------------------------------------------------------------- 1 | name,surname,age,language,website 2 | Brais,Moure,35,Python,https://moure.dev 3 | Roswell,,2,COBOL, 4 | -------------------------------------------------------------------------------- /Intermediate/my_file.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Brais", 3 | "surname": "Moure", 4 | "age": 35, 5 | "languages": [ 6 | "Python", 7 | "Swift", 8 | "Kotlin" 9 | ], 10 | "website": "https://moure.dev" 11 | } -------------------------------------------------------------------------------- /Intermediate/my_file.txt: -------------------------------------------------------------------------------- 1 | Mi nombre es Brais 2 | Mi apellido es Moure 3 | 35 años 4 | Y mi lenguaje preferido es Python 5 | Aunque también me gusta Kotlin 6 | Y Swift -------------------------------------------------------------------------------- /Intermediate/mypackage/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CamiloHCardona/https-github.com-mouredev-Hello-Python/fcfc58b7452edc4364010cd109db6e3628466da3/Intermediate/mypackage/__init__.py -------------------------------------------------------------------------------- /Intermediate/mypackage/arithmetics.py: -------------------------------------------------------------------------------- 1 | # Clase en vídeo: https://youtu.be/TbcEqkabAWU?t=24010 2 | 3 | ### Arithmetics ### 4 | 5 | def sum_two_values(first_value, second_value): 6 | return first_value + second_value 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hello Python 2 | 3 | [![Python](https://img.shields.io/badge/Python-3.10+-yellow?style=for-the-badge&logo=python&logoColor=white&labelColor=101010)](https://python.org) 4 | [![FastAPI](https://img.shields.io/badge/FastAPI-0.88.0+-00a393?style=for-the-badge&logo=fastapi&logoColor=white&labelColor=101010)](https://python.org) 5 | [![MongoDB](https://img.shields.io/badge/MongoDB-6.0+-00684A?style=for-the-badge&logo=mongodb&logoColor=white&labelColor=101010)](https://python.org) 6 | 7 | ## Curso para aprender el lenguaje de programación Python desde cero y para principiantes 8 | 9 | ![](./Images/header.jpg) 10 | 11 | ### Proyecto realizado durante emisiones en directo desde [Twitch](https://twitch.tv/mouredev) 12 | > ##### Si consideras útil el curso, apóyalo haciendo "★ Star" en el repositorio. ¡Gracias! 13 | 14 | ## Clases en vídeo 15 | 16 | ### Curso de fundamentos desde cero 17 | 18 | Curso que agrupa todas las clases en directo que hacen referencia a los fundamentos de Python. 19 | 20 | > Código: Directorio "Basic" en el proyecto 21 | 22 | 23 | 24 | * [Introducción](https://youtu.be/Kp4Mvapo5kc) 25 | * [Contexto](https://youtu.be/Kp4Mvapo5kc?t=244) 26 | * [Lección 1 - Configuración](https://youtu.be/Kp4Mvapo5kc?t=850) 27 | * [Lección 2 - Hola Mundo](https://youtu.be/Kp4Mvapo5kc?t=1518) 28 | * [Lección 3 - Variables](https://youtu.be/Kp4Mvapo5kc?t=2938) 29 | * [Lección 4 - Operadores](https://youtu.be/Kp4Mvapo5kc?t=5665) 30 | * [Lección 5 - Strings](https://youtu.be/Kp4Mvapo5kc?t=8643) 31 | * [Lección 6 - Listas](https://youtu.be/Kp4Mvapo5kc?t=10872) 32 | * [Lección 7 - Tuplas](https://youtu.be/Kp4Mvapo5kc?t=14711) 33 | * [Lección 8 - Sets](https://youtu.be/Kp4Mvapo5kc?t=16335) 34 | * [Lección 9 - Diccionarios](https://youtu.be/Kp4Mvapo5kc?t=18506) 35 | * [Lección 10 - Condicionales](https://youtu.be/Kp4Mvapo5kc?t=21442) 36 | * [Lección 11 - Bucles/Loops/Ciclos](https://youtu.be/Kp4Mvapo5kc?t=23822) 37 | * [Lección 12 - Funciones](https://youtu.be/Kp4Mvapo5kc?t=26619) 38 | * [Lección 13 - Clases](https://youtu.be/Kp4Mvapo5kc?t=29327) 39 | * [Lección 14 - Excepciones](https://youtu.be/Kp4Mvapo5kc?t=32030) 40 | * [Lección 15 - Módulos](https://youtu.be/Kp4Mvapo5kc?t=34583) 41 | * [Próximos pasos](https://youtu.be/Kp4Mvapo5kc?t=36390) 42 | 43 | ### Curso intermedio de fundamentos desde cero 44 | 45 | Curso en el que continuamos aprendiendo Python desde sus bases, siguiendo la ruta de aprendizaje desde la última lección del curso de inicial. 46 | 47 | > Código: Directorio "Intermediate" en el proyecto 48 | 49 | 50 | 51 | * [Introducción](https://youtu.be/TbcEqkabAWU) 52 | * [Lección 1 - Dates](https://youtu.be/TbcEqkabAWU?t=202) 53 | * [Lección 2 - List Comprehension](https://youtu.be/TbcEqkabAWU?t=3239) 54 | * [Lección 3 - Resolución de retos de programación](https://youtu.be/TbcEqkabAWU?t=4142) 55 | * [Lección 4 - Lambdas](https://youtu.be/TbcEqkabAWU?t=9145) 56 | * [Lección 5 - Funciones de orden superior](https://youtu.be/TbcEqkabAWU?t=10172) 57 | * [Lección 6 - Tipos de error](https://youtu.be/TbcEqkabAWU?t=12721) 58 | * [Lección 7 - Manejo de ficheros](https://youtu.be/TbcEqkabAWU?t=15524) 59 | * [Lección 8 - Expresiones regulares](https://youtu.be/TbcEqkabAWU?t=19762) 60 | * [Lección 9 - Manejo de paquetes](https://youtu.be/TbcEqkabAWU?t=24010) 61 | * [Próximos pasos](https://youtu.be/TbcEqkabAWU?t=26228) 62 | 63 | ### Backend desde cero 64 | 65 | Curso en el que aprenderemos a utilizar Python para backend e implementaremos un API REST con autenticación, base de datos y desplegaremos el proyecto en un servidor real. 66 | 67 | > Código: Directorio "Backend" en el proyecto 68 | 69 | 70 | 71 | * [Introducción](https://youtu.be/_y9qQZXE24A) 72 | * [Lección 01 - ¿Qué es un backend?](https://youtu.be/_y9qQZXE24A?t=125) 73 | * [Lección 02 - API y FastAPI](https://youtu.be/_y9qQZXE24A?t=834) 74 | * [Lección 03 - Type Hints](https://youtu.be/_y9qQZXE24A?t=1810) 75 | * [Lección 04 - Configuración FastAPI](https://youtu.be/_y9qQZXE24A?t=2629) 76 | * [Lección 05 - Hola mundo](https://youtu.be/_y9qQZXE24A?t=3504) 77 | * [Lección 06 - Operación GET](https://youtu.be/_y9qQZXE24A?t=5382) 78 | * [Lección 07 - Peticiones HTTP](https://youtu.be/_y9qQZXE24A?t=5925) 79 | * [Lección 08 - Creación API](https://youtu.be/_y9qQZXE24A?t=6099) 80 | * [Lección 09 - Path y Query](https://youtu.be/_y9qQZXE24A?t=7510) 81 | * [Lección 10 - Operaciones POST, PUT y DELETE](https://youtu.be/_y9qQZXE24A?t=8529) 82 | * [Lección 11 - HTTP status codes](https://youtu.be/_y9qQZXE24A?t=11072) 83 | * [Lección 12 - Routers](https://youtu.be/_y9qQZXE24A?t=12475) 84 | * [Lección 13 - Recursos estáticos](https://youtu.be/_y9qQZXE24A?t=13618) 85 | * [Lección 14 - Autorización OAuth2](https://youtu.be/_y9qQZXE24A?t=14094) 86 | * [Lección 15 - OAuth2 JWT](https://youtu.be/_y9qQZXE24A?t=17664) 87 | * [Lección 16 - MongoDB](https://youtu.be/_y9qQZXE24A?t=20480) 88 | * [Lección 17 - MongoDB Atlas](https://youtu.be/_y9qQZXE24A?t=25470) 89 | * [Lección 18 - Despliegue en Deta](https://youtu.be/_y9qQZXE24A?t=27335) 90 | * [Lección Próximos pasos](https://youtu.be/_y9qQZXE24A?t=28484) 91 | 92 | ## Información importante y preguntas frecuentes 93 | 94 | Actualmente el curso está en pausa. Se han finalizados los bloques básico, intermedio y backend, y ese era el objetivo inicial del proyecto. 95 | No descarto añadir nuevas lecciones a futuro, pero creo que por el momento puede servir de base a cualquier persona que quiera empezar a aprender este lenguaje. 96 | 97 | * Recuerda que he creado en el [Discord](https://discord.gg/mouredev) un canal "🐍python" para que puedas comentar lo que quieras. 98 | * En el momento que el curso continúe, actualizaré el repositorio y avisaré en redes. 99 | 100 | ¡Muchísimas gracias por todo el apoyo mostrado! 101 | 102 | ## Enlaces de interés 103 | 104 | * [Web oficial de Python](https://www.python.org/) 105 | * [Tutorial oficial de Python en Español](https://docs.python.org/es/3/tutorial/index.html) 106 | * [Repo 30 días de Python](https://github.com/Asabeneh/30-Days-Of-Python) 107 | * [Juego Codédex para aprender Python](https://www.codedex.io/) 108 | * [Visual Studio Code](https://code.visualstudio.com/): El editor que estoy usando 109 | * [FastAPI](https://fastapi.tiangolo.com/es/): El framework para crear nuestra API Backend 110 | * [MongoDB](https://www.mongodb.com/): La base de datos que utiliza nuestro backend 111 | * [Deta](https://www.deta.sh/): Para desplegar nuestra API en la nube 112 | 113 | #### Puedes apoyar mi trabajo haciendo "☆ Star" en el repo o nominarme a "GitHub Star". ¡Gracias! 114 | 115 | [![GitHub Star](https://img.shields.io/badge/GitHub-Nominar_a_star-yellow?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://stars.github.com/nominate/) 116 | 117 | Si quieres unirte a nuestra comunidad de desarrollo, aprender programación de Apps, mejorar tus habilidades y ayudar a la continuidad del proyecto, puedes encontrarnos en: 118 | 119 | [![Twitch](https://img.shields.io/badge/Twitch-Programación_en_directo-9146FF?style=for-the-badge&logo=twitch&logoColor=white&labelColor=101010)](https://twitch.tv/mouredev) 120 | [![Discord](https://img.shields.io/badge/Discord-Servidor_de_la_comunidad-5865F2?style=for-the-badge&logo=discord&logoColor=white&labelColor=101010)](https://mouredev.com/discord) 121 | [![Link](https://img.shields.io/badge/Links_de_interés-moure.dev-39E09B?style=for-the-badge&logo=Linktree&logoColor=white&labelColor=101010)](https://moure.dev) 122 | 123 | ## ![https://mouredev.com](https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_emote.png) Hola, mi nombre es Brais Moure. 124 | ### Freelance full-stack iOS & Android engineer 125 | 126 | [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCxPD7bsocoAMq8Dj18kmGyQ?style=social)](https://youtube.com/mouredevapps?sub_confirmation=1) 127 | [![Twitch Status](https://img.shields.io/twitch/status/mouredev?style=social)](https://twitch.com/mouredev) 128 | [![Discord](https://img.shields.io/discord/729672926432985098?style=social&label=Discord&logo=discord)](https://mouredev.com/discord) 129 | [![Twitter Follow](https://img.shields.io/twitter/follow/mouredev?style=social)](https://twitter.com/mouredev) 130 | ![GitHub Followers](https://img.shields.io/github/followers/mouredev?style=social) 131 | ![GitHub Followers](https://img.shields.io/github/stars/mouredev?style=social) 132 | 133 | Soy ingeniero de software desde hace más de 12 años. Desde hace 4 años combino mi trabajo desarrollando Apps con creación de contenido formativo sobre programación y tecnología en diferentes redes sociales como **[@mouredev](https://moure.dev)**. 134 | 135 | ### En mi perfil de GitHub tienes más información 136 | 137 | [![Web](https://img.shields.io/badge/GitHub-MoureDev-14a1f0?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev) 138 | --------------------------------------------------------------------------------