- Frontendmasters: Practical Guide to Python
- Aquí está la url del contenido del curso: learnpython.
- REPL: Read Evaluate Print Loop. Puedes considerarlo más tu área de bosquejo, donde puedes probar y experimentar con tu código de Python.
- Puedes escribir en la consola de Python
import this
y obtendrás los 19 principios de Python. - Hay un par de comandos easter egg que puedes obtener escribiendo:
from __future__ import braces
yimport antigravity
. - Normalmente el punto de entrada de un programa de Python está en
"__main__"
, es por eso que verás en cada programa la siguiente línea de códigoif __name__ = "__main__:"
, que es donde Python comenzará a correr el código que escribiste.
- Es importante recordar que Python es un lenguaje dinámico, esto quiere decir que no tienes que decirle a Python el tipo de lo que estás escribiendo.
- Cuando crees variables, debes ser lo más explícito posible al nombrar las variables.
- Para Python se definen las variables de acuerdo a la convención
snake_casing
. - Es importante saber que no puedes definir una variable que comience con número y tener cuidado de no usar
special keywords
(palabras reservadas) de Python al nombrar variables. - Puedes acceder al listado de palabras reservadas escribiendo en la consola de Python
help()
y despuéskeywords
, y obtendrás la siguiente lista:
Here is a list of the Python keywords. Enter any keyword to get more help.
Palabra | Palabra | Palabra | Palabra | Palabra |
---|---|---|---|---|
False | await | else | import | pass |
None | break | except | in | raise |
True | class | finally | is | return |
and | continue | for | lambda | try |
as | def | from | nonlocal | while |
assert | del | global | not | with |
async | elif | if | or | yield |
- Los tres métodos REPL que más uso darás en tu carrera como programador Python son:
help()
(te da una ayuda de Python),type()
(te devuelve el tipo de lo que introduzcas como parámetro) ydir()
(te devuelve un listado de todos los métodos disponibles de lo que introduzcas como parámetro). - En los cálculos con valores numéricos, al hacer
25 / 5
te devolverá un tipofloat
, pero puedes evitarlo haciéndo el cálculo de la siguiente manera25 // 5
y te devolverá el resultado comoint
. - Para los strings, es recomendable usar
double quotes
, de esta forma al usar algo comodon't...
no tendrás errores en la consola y tus variables siempre estarán escritas de la misma forma (con comillas dobles). - Si vas a escribir un string largo, se puede usar
""""
para definirlo, cerrando de la misma forma con tres comillas dobles. - Puedes concatenar strings con el símbolo
+
. - Puedes usar una
f
al inicio de un string, y de esta forma puedes agregar variables y/o expresiones a tu string, lo que te permite agregarle el valor de tus variables. Ejemplo:
a = 37
f"Mi edad es de {a} años" # Mi edad es de 37 años
- Se puede declarar una lista con
[]
o conlist()
- Son pequeñas colecciones en las que puedes poner diferentes tipos de items. A diferencia de las listas que son usadas generalmente para contener tipos similares de items, las tuplas no tienen restricciones en esa área.
- Otra diferencia entre las listas y las tuplas es que las tuplas son
inmutables
. - Las listas son creadas con
[]
, pero las tuplas son creadas con()
. - Para que una tupla de un solo elemento sea de tipo tupla, debe cumplir con la condición de tener una coma después del elemento
(1,)
. - Se puede hacer una extracción de valores y asignarlos en una variable de la siguiente manera:
student = ("Jesús", 37, "History", 9.5)
name, age, subject, gpa = student
name # Jesús
age # 37
subject # History
gpa # 9.5
- Para lo anterior, se debe cumplir una condición importante, y es que las variables a definir deben cumplir con el número de índices dentro de la tupla.
- Se puede omitir el uso de alguno de los índices con
_
, por ejemplo, de acuerdo al código de arribaname, age, subject, _ = student
, con esto el último valor no estará guardado en ninguna variable.
- Son tipo mutable y solo te permiten contener tipos inmutables dentro y de manera desordenada.
- Otra característica es que son rápidos. Por lo mismo que están bien definidos y no contienen: lists, dictionaries, y otros tipos mutables.
- Para crear set puedes hacerlo con
{}
y conset()
, pero como nota importante, no puedes crear un set vacío con{}
, porque Python lo reconocería como un tipodict
, para crear un set vacío, lo puedes hacer con la instrucciónset()
. - Set puede tener un solo ítem dentro o múltiples.
- Set no puede contener valores duplicados, por ejemplo si creo una variable
my_set = {3, 3, 4,}
, mi variable al llamarla será{3, 4}
. - Hay un tip para saber qué es mutable y qué no lo es con el método
hash()
:
hash(5)
# 5
hash("Hello")
# -6361881465459099289
hash(["Hello"])
# Traceback (most recent call last):
# File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py", line 364, in runcode
# coro = func()
# File "<input>", line 1, in <module>
# TypeError: unhashable type: 'list'
- Puedes crear un set de un array existente y evitar los duplicados al mismo tiempo. Ejemplo:
names = ["Aleisa", "Aleisa", "Tiana", "Jana"]
set(names)
# {'Jana', 'Tiana', 'Aleisa'}
- Es un tipo de dato mutable que nos permite guardar
key
yvalue
emparejados. - Como se mencionó arriba, son inmutables, pero el dictionary key debe ser inmutable, por qué, porque los
key
de los dictionaries deben serhashables
. De esta manera Python se asegura de realizar búsquedas rápidas. - Los dictionaries se definen con
{}
, para crear un dict vacío, basta con escribir{}
, y para crear uno con elementos debe cumplir la regla{key: value}
. - Puedes acceder a los valores del dict con la connotación
my_dict[key]
. Por ejemplo:
my_dict = {"one": 1, "two": 2}
my_dict["one"]
# 1
- Pero no puedes acceder a un valor por "índice"
my_dict[0]
, porque la restricción es que se le indique elkey
para que sea válido. - Hay tres métodos muy útiles que se usarán mucho con los dicts:
my_dict = {"one": 1, "two": 2}
my_dict["three"] = 3
my_dict
# {'one': 1, 'two': 2, 'three': 3}
my_dict.keys()
# dict_keys(['one', 'two', 'three'])
my_dict.values()
# dict_values([1, 2, 3])
my_dict.items()
# dict_items([('one', 1), ('two', 2), ('three', 3)])
- Recuerda que para nombrar variables como para nombrar archivos se hace con
lowercase
ysnake_case
, además, a diferencia de los nombres de variables que deben ser muy descriptivos, los archivos deben ser de preferencia nombres cortos. - Vas a encontrar de repente algunos archivos con extensión
pyc
, no te preocupes, son archivos para optimización, solo no hagas commit de ellos. En caso de que creas que hay algúnpyc
escondido y temes que se haga commit de él, prueba corriendo el siguiente comandofind . --name "*.pyc" --delete
. - Para correr un programa de Python, asegúrate de estar en tu ambiente virtual y correr
python <file_name>
. - Si quieres ver el resultado de tus programas, vas a tener que usar print para ver lo que deseas que se imprima en la terminal, solo evita hacer esto a nivel producción.
- Existe una librería dentro de python para imprimir de manera más legible, su nombre es
pretty print
y se usaimport pprint
y en vez de usarprint(...)
vas a usarpprint(...)
.
- Las funciones se definen
def my_func_name():
, es importante tener los dos puntos al final de la declaración, y todo lo que va dentro de la función debe ir con espacios para que vaya dentro de su contexto. - Es importante considerar dejar un espacio después de terminar tu función, por cuestiones de lectura adecuada del programa.
- Las funciones deben retornar algo, en caso de que no lo hagas, al leer su tipo, tendrás como respuesta
NoneType
. - Una función puede aceptar todos los argumentos que quieras, separados de comas, y esos argumentos serán usados dentro de la función para el propósito que quieres.
- Si al crear una función decides que uno de los argumentos puede no ir al llamar la función, pero deseas incluir un valor default, lo puedes hacer:
def my_sum_func(x, y, z=1):
return x + y + z
my_sum_func(5, 5)
# 11 porque z tiene un valor default de 1
my_sum_func(5, 5, 5)
# 15
- De acuerdo a lo anterior, entonces tenemos que existe un orden para la definición de una función con argumentos opcionales, primero van los argumentos requeridos y al final los argumentos opcionales.
- Puedes llamar a la función con los argumentos en desorden, siempre y cuando le digas a Python el valor específico de casa argumento para que pueda hacer la lectura adecuada:
def my_sum_func(x, y, z=1):
return x + y + z
my_sum_func(y=4, z=2, x=10)
# 16
- No ocupes argumentos mutables como default values en la definición de tu función, ya que no se comportarán de la manera en que probablemente esperas. Ejemplo:
def do_stuff(list_two=[]):
list_two.append("stuff!")
return list_two
do_stuff()
# ['stuff!']
do_stuff()
# ['stuff!', 'stuff!']
do_stuff()
# ['stuff!', 'stuff!', 'stuff!']
- El scope de cada función le pertenece a cada variable que se defina dentro de la función y no afuera de ella. Ejemplo:
name = "Alex"
print(f"Name OUTSIDE the function is: {name}")
# Name OUTSIDE the function is: Alex
def try_change_name():
name = "Max"
print(f"Name INSIDE the function is: {name}")
try_change_name()
# Name INSIDE the function is: Max
name
# 'Alex'
- Por lo tanto, no trates de querer cambiar una variable que fue definida fuera de la función, porque no será posible, aunque tienes acceso a ella y es muy útil (como usar una variable global
url
por ejemplo), el scope no es el mismo. - Una recomendación es que si vas a definir una constante, la definas con
MAYUSCULAS_Y_SEPARADAS_CON_GUION_BAJO
.
Thruthiness
evalúa una expresión si esFalse
oTrue
.- Con los tipos
int
losceros
sonFalse
y todos los demás números incluidos los negativos sonTrue
. - Para los otros tipos de valores como
list
,tuple
,set
ydict
todos los contenedores vacíos sonFalse
y los que tienen al menos un elemento son evaluados comoTrue
.None
siempre seráFalse
. - Para hacer una evaluación puedes usar
bool()
, también con una expresión de comparación con==
o!=
. - Puedes intentar validar si es verdad que dos listas son iguales, pero a continuación se muestra la forma incorrecta y correcta de hacerlo:
list_one = [1, 2, 3]
list_two = [1, 2, 3]
list_one == list_two
# True
list_one is list_two # ¿Esta es la manera correcta de validar, porque checa la identidad, osea, esto apunta al mismo lugar en memoria?
# False
x = None
x is None
# True
[] is None
# False
- Igualmente se tienen
and
,or
,not
. Por ejemplo:
a = True
b = True
a and b
# True
True and False
# False
True or False
# True
True or True
# True
False or False
# False
a
# True
not a
# False
True and (True or False)
# True
- Puedes usar
if
para hacer comparaciones con diferentes expresiones y definir cuando retornar algo o no. Por ejemplo:
if 3 < 5:
print("Hi")
# Hi
if 5 < 3:
print("Hi")
a = True
b = False
if not b:
print("Hi")
# Hi
if []:
print("Hi")
if [1, 2]:
print("Hi")
# Hi
- También existe
else
para cuando la condición en elif
no sea True. Ejemplo:
if 5 < 3:
print("Hi")
else:
print("Bye")
# Bye
- Los
for
loops en Python son simples de leer y escribir, la idea es recorrer un arreglo de valores, creando una variable temporal que será el índice que corresponde como valor:for temp_value in array:
. Ejemplo:
colors = ["Red", "White", "Green", "Blue"]
for color in colors:
print(f"The color is: {color}")
# The color is: Red
# The color is: White
# The color is: Green
# The color is: Blue
- Es importante resaltar, que el valor de
color
sigue existiendo aún fuera del scope delfor loop
, y este tiene el último valor obtenido al recorrer el arreglo. - Puedes crear un arreglo con
range()
de la siguiente manera:
list(range(3))
# [0, 1, 2]
list(range(3, 7))
# [3, 4, 5, 6]
for number in range(3, 7):
print(number)
# 3
# 4
# 5
# 6
- Puedes también obtener el valor y el índice de un arreglo con
enumerate()
respondiendo con una lista de tuplas de la siguiente forma:
colors = ['Red', 'White', 'Green', 'Blue']
list(enumerate(colors))
# [(0, 'Red'), (1, 'White'), (2, 'Green'), (3, 'Blue')]
colors
# ['Red', 'White', 'Green', 'Blue']
for index, color in enumerate(colors):
print(f"{index} color at: {color}")
# 0 color at: Red
# 1 color at: White
# 2 color at: Green
# 3 color at: Blue
- Si queremos recorrer un
dict
debemos tener presente que por default undict
nos va a devolver las keys. Así que necesitamos pedir explícitamente por las keys y values. Por ejemplo:
hex_colors = {
"Red": "#FF0000",
"Green": "#008000",
"Blue": "#0000FF",
}
for hex_color in hex_colors:
print(hex_color)
# Red
# Green
# Blue
hex_colors.items()
# dict_items([('Red', '#FF0000'), ('Green', '#008000'), ('Blue', '#0000FF')])
for key, value in hex_colors.items():
print(f"{key} is value: {value}")
# Red is value: #FF0000
# Green is value: #008000
# Blue is value: #0000FF
- Este es uno de los feature únicos con los que cuenta solo Python, y que incluso por su efectividad, algunos otros lenguajes de programación están comenzando a implementar.
- Veamos un ejemplo de cómo se ve al tomar una lista de nombres y devolvamos una lista de la longitud de cada nombre aquí:
- Se puede también incluir condicionales en las
list comprehensions
:
names = ['Alex', 'Elo', 'Tiana', 'Aleisa', 'Jana', 'Ester']
[name for name in names if len(name) % 2 == 0]
# ['Alex', 'Aleisa', 'Jana'] Me está devolviendo solo los nombres que tienen una longitud par
- Una forma práctica de crear una lista de un arreglo de nombres dividido por comas es
split()
:
names_string = "Alex,Elo,Tiana,Aleisa,Jana,Ester"
names_string.split(",")
# ['Alex', 'Elo', 'Tiana', 'Aleisa', 'Jana', 'Ester']
- También puedes pasar de una lista a un string con
join()
:
names_string = "Alex,Elo,Tiana,Aleisa,Jana,Ester"
names_list = names_string.split(",")
" - ".join(names_list)
# 'Alex - Elo - Tiana - Aleisa - Jana - Ester'
- Se pueden realizar operaciones en una
list comprehension
:
num_list = [1, 2, 3]
[num * 2 for num in num_list]
# [2, 4, 6]
", ".join([str(num * 2) for num in num_list])
# '2, 4, 6'
- Parece una
list comprehension
, pero a diferencia de estas, se escribe con paréntesis. Al final, este nos devuelve un tipogenerator
. Veamos un ejemplo:
# List comprehension
list_comp = [x ** 2 for x in range(10) if x % 2 == 0]
list_comp
# [0, 4, 16, 36, 64]
type(list_comp)
# <class 'list'>
# Generator expression
gen_exp = (x ** 2 for x in range(10) if x % 2 == 0)
gen_exp
# <generator object <genexpr> at 0x1017854a0>
type(gen_exp)
# <class 'generator'>
- Los generadores no ocupan todo el espacio en memoria del resultado obtenido, puedes recorrer el
generator
como lo hemos venido haciendo, pero, hay una diferencia con un arreglo normal, y es que al no tener el espacio en memoria usado, este después de usarse queda exhausto, o sea, ya no es más útil.
gen_exp = (x ** 2 for x in range(10) if x % 2 == 0)
for item in gen_exp:
print(item)
# 0
# 4
# 16
# 36
# 64
for item in gen_exp:
print(item)
- Everything is an object in Python.
- Classes are not the same with Instances. For example:
43
is an instance of theclass
int
, andint
como tal es elobjeto clase
. - Puedes pensar en una clase como un tipo de algo, como un
carro
, y en la instancia como algo específico de ese tipo de cosa, como mi carroNissan
, que es un tipo decarro
. - Ambos pueden tener en ellos
variables
y/ométodos
. - Cuando cambias una variable de la clase, va a cambiar lo que estás retornando cuando llamas a la instancia de esa clase, pero cuando cambias cosas en una instancia, eso nunca va a afectar a la clase que la contiene.
self
es usado en las clases para referir a abundar o manar una instancia de esa variable u objeto. Por ejemplo:
class Car:
runs = True
def start(self):
if self.runs:
print("Car is started. Vroom vroom!")
else:
print("Car is broken :(")
my_car = Car()
print(f"My car runs: {my_car.runs}")
my_car.start()
# My car runs: True
# Car is started. Vroom vroom!
my_car.runs = False
print(f"My car runs: {my_car.runs}")
my_car.start()
# My car runs: False
# Car is broken :(
my_other_car = Car()
my_other_car.start()
# Car is started. Vroom vroom!
- Entonces, de acuerdo al ejemplo anterior, también podemos concluir que
self
refiere a una instancia. - Todas las variables in estas clases deben poner a
self
como primer argumento. - Por ejemplo, si trato de llamar
start()
en la claseCar()
, en vez de hacerlo por medio de una instancia, recibiremos un error:
class Car:
runs = True
def start(self):
if self.runs:
print("Car is started. Vroom vroom!")
else:
print("Car is broken :(")
Car.start()
# Traceback (most recent call last):
# File "./python-practical-guide/chapter_6.py", line 11, in <module>
# Car.start()
# TypeError: start() missing 1 required positional argument: 'self'
#
# Process finished with exit code 1
- Este error es muy común, y en este caso sucede porque estoy tratando de llamar el método
start()
, el cual es un método instancia, por lo tanto, está esperando una instancia en la misma clase. - Por ejemplo si intentas al método correctamente a través de la instancia, pero sin haber agregado
self
en la instancia, tendrás otro error muy común.
class Car:
runs = True
def start():
pass
# if self.runs:
# print("Car is started. Vroom vroom!")
# else:
# print("Car is broken :(")
my_new_car_two = Car()
my_new_car_two.start()
# Traceback (most recent call last):
# File "./python-practical-guide/chapter_6.py", line 13, in <module>
# my_new_car_two.start()
# TypeError: start() takes 0 positional arguments but 1 was given
#
# Process finished with exit code 1
- Las clases también pueden contener clases dentro, lo que hace innecesario incluir el argumento
self
en ellas. Para ello, existe unaAnnotation
que podemos incluir por encima de la clase llamada@classmethod
, para decirle a Python que este método no espera una instancia en él. Por el contrario, el argumento que puede llevar escls
, con el que podemos acceder a las variables definidas al inicio de laclass
:
class Car:
runs = True
number_of_wheels = 4
@classmethod
def get_number_of_wheels(cls):
return cls.number_of_wheels
def start(self):
if self.runs:
print("Car is started. Vroom vroom!")
else:
print("Car is broken :(")
- Hay una forma de descubrir cuando algo es instancia de una clase, como cuando evaluamos el
type
:
class Car:
runs = True
number_of_wheels = 4
@classmethod
def get_number_of_wheels(cls):
return cls.number_of_wheels
def start(self):
if self.runs:
print("Car is started. Vroom vroom!")
else:
print("Car is broken :(")
my_car = Car()
isinstance(42, int)
# True
isinstance("Hello world!", str)
# True
isinstance(my_car, float)
# False
isinstance(my_car, Car)
# True
- Los
magic methods
son reconocidos por tener doble guion bajo antes y después de su nombre, como es el caso de__init__
. Eso significa que hay algo especial en estas funciones o métodos. - En este caso
dunder init (__init__)
, va a correr en el momento que crees una instancia de esa clase, y debe llevarself
, además que puedes incluir los argumentos que desees y que van a estar disponibles en la clase para su uso.
class Car:
runs = True
def __init__(self, make, model):
self.make = make
self.model = model
def start(self):
if self.runs:
print(f"Your {self.make} {self.model} is started. Vroom vroom!")
else:
print(f"Your {self.make} {self.model} is broken :(")
my_car = Car("Ford", "Thunderbird")
my_car.start()
# Your Ford Thunderbird is started. Vroom vroom!
- En el ejemplo de arriba, podemos ver que existen dos argumentos requeridos, que si al crear una instancia de esa clase sin esos argumentos, obtendrás un error. Además, si quiero salvar esos valores para que sean usados después, debo guardarlos en la instancia como se muestra:
def __init__(self, make, model):
self.make = make
self.model = model
- Esto significa que una vez guardados de esta forma en la instancia, podré usarlos cuando llame otros métodos.
- Hay otros
magic methods
comodunder str (__str__)
ydunder repr (__repr__)
, los cuales son muy comúnmente usados para hacer debugging. Ambos devuelven unstring
. __str__
lo puedes ver como una representación de tu objeto que puede ser leído humanamente, algo que puedes mostrarle al usuario para hacerle saber lo que representa tu objeto.__repr__
retorna el código de Python que probablemente sea necesario para reconstruir el objeto. Así que este método es más usado bajo el agua.
import datetime
now = datetime.datetime.now()
str(now)
# '2023-02-22 18:40:55.154714'
repr(now)
# 'datetime.datetime(2023, 2, 22, 18, 40, 55, 154714)'
Otro ejemplo:
class Car:
def __init__(self, make, model):
self.make = make
self.model = model
def __str__(self):
return f"<<Car object: {self.make} {self.model}>>"
def __repr__(self):
return f"Car('{self.make}', '{self.model}')"
my_car = Car("Ford", "Thunderbird")
print(f"This object is a {str(my_car)}")
print(f"To reproduce it, type: {repr(my_car)}")
# This object is a <<Car object: Ford Thunderbird>>
# To reproduce it, type: Car('Ford', 'Thunderbird')
- Python tiene herencia y también herencia múltiple.
- Cuando una clase hereda de otra, debes poner la clase de la que heredarás en el paréntesis, después de la definición de la propia clase.
- Entonces, cuando llamas
__init__
dentro de la subclase, si quieres correr todo el código de lasuperclase
, necesitas entonces llamar explícitamentesuper()
y el método que llamarás, junto con todos sus argumentos:
class Vehicle:
def __init__(self, make, model, fuel="gas"):
self.make = make
self.model = model
self.fuel = fuel
class Car(Vehicle):
def __init__(self, make, model, fuel="gas"):
super().__init__(make, model, fuel)
- Si llegáramos a tener una excepción no detectada
uncaught exception
en nuestro programa, el programa se saldrá rotundamente, y no continuará con su ejecución.
int("a")
print("End of the program.")
# Traceback (most recent call last):
# File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py", line 364, in runcode
# coro = func()
# File "<input>", line 2, in <module>
# ValueError: invalid literal for int() with base 10: 'a'
- Como puedes ver en el ejemplo de arriba, el programa nunca llegó a la línea de
print()
. - Para ello, Python cuenta con una forma de cachar excepciones y es con
try
yexcept
.
try:
int("a")
except ValueError:
print("Oops, couldn't convert that value into an int!")
print("Reached end of the program.")
# Oops, couldn't convert that value into an int!
# Reached end of the program.
- Siempre debemos pensar en cachar excepciones lo más específicas posibles. Como en el ejemplo de arriba, que aprendió del error lanzado en el primer error:
ValueError: invalid literal for int() with base 10: 'a'
, lo cual ayudó a copiar la claseValueError
y con eso se incluyó en la solución. - Otra cosa a considerar, es que en
try
yexcept
se lanzará el error en el orden en que sea encontrado.
try:
d = {}
d["a"]
int("a")
except ValueError:
print("Oops, couldn't convert that value into an int!")
print("Reached end of the program.")
# Traceback (most recent call last):
# File "/Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py", line 364, in runcode
# coro = func()
# File "<input>", line 3, in <module>
# KeyError: 'a'
- Entonces una solución es incluir las excepciones que sean necesarias:
try:
d = {}
d["a"]
int("a")
except ValueError:
print("A value exception happened.")
except KeyError:
print("A key wasn't found.")
print("Reached end of the program.")
# A key wasn't found.
# Reached end of the program.
- También existe una cláusula
finally
que puedes incluir como un bloque opcional, el cual correrá después de que el try se haya ejecutado y lanzado o no alguna excepción. Así que si quieres hacer algún tipo de limpieza, ese es el lugar correcto para hacerlo. - Como NOTA IMPORTANTE nunca hagas
catch
deExeption
yBaseException
, sobre todo la última, porque estarás exceptuando del programa todas las excepciones, las cuales están incluidas enBaseException
, incluso no te será posible hacerCTRL + C
para salir de la ejecución del programa.
- El propósito del
main method
es que solamente correrá cuando tu código sea ejecutado como un programa independiente. Lo que quiere decir que puede ser importado en otros proyectos conimport
. Esto es muy útil cuando queremos escribir código reutilizable. Por ejemplo:
# name_lib.py
def name_length(name):
return len(name)
def upper_case_name(name):
return name.upper()
def lower_case_name(name):
return name.lower()
name = "Nina"
length = name_length(name)
upper_case = upper_case_name(name)
print(f"The length is {length} and the uppercase version is: {upper_case}")
# other_program.py
import name_lib
my_name = "Fred"
my_length = name_lib.name_length(my_name)
my_lower_case = name_lib.lower_case_name(my_name)
print(f"In my code, my length is {my_length} and my lower case name is: {my_lower_case}")
# The length is 4 and the uppercase version is: NINA
# In my code, my length is 4 and my lower case name is: fred
- Este resultado no es esperado, porque en el último programa que estoy corriendo, se está ejecutando
name_lib.py
y el print que hay enother_program.py
. Para evitar eso, debemos wrappear nuestro programa en un__main__
.
# name_lib.py
def name_length(name):
return len(name)
def upper_case_name(name):
return name.upper()
def lower_case_name(name):
return name.lower()
if __name__ == "__main__":
name = "Nina"
length = name_length(name)
upper_case = upper_case_name(name)
print(f"The length is {length} and the uppercase version is: {upper_case}")
# *****************************************************************************
# other_program.py
import name_lib
my_name = "Fred"
my_length = name_lib.name_length(my_name)
my_lower_case = name_lib.lower_case_name(my_name)
print(f"In my code, my length is {my_length} and my lower case name is: {my_lower_case}")
# In my code, my length is 4 and my lower case name is: fred
- Los
virtual environments
son muy útiles para almacenar las dependencias que requiere nuestra aplicación Python. - La creación de un entorno virtual crea una carpeta independiente que incluye una instalación completa de Python, lo que le permite instalar dependencias específicas de su aplicación (o incluso una versión específica de Python si lo desea) sin depender de la versión del sistema global de Python.
- Un standard que verás en Python es un archivo llamado
requirements.txt
que está incluido en los proyectos de Python. Es un archivo especial que usaremos para decirle apip
(Python Package Manager). - Puedes crear manualmente tu archivo agregando cada librería usada en tu proyecto, o puedes crearlo con el comando
pip freeze > requirements.txt
y/o ejecutarlo en un nuevo ambiente donde continuarás tu trabajo con el comandopip install -r requirements.txt
.
- Puedes importar librerías completas solo haciendo
import random
por ejemplo, o puedes importar los métodos que necesites de esa librería, solo los que vayas a usar en tu proyecto confrom random import randint
- También puedes instalar librerías con el comando
python -m pip install request
. Lo que hace este comando es asegurarse quepip
instalará la librería que haga match en la versión de tu environment y no tendrás problemas de tener instaladas versiones que no funcionan para tu proyecto dePython
ypip
.
python -m pip install requests
# Requirement already satisfied: requests in ./venv/lib/python3.9/site-packages (2.28.2)
# Requirement already satisfied: certifi>=2017.4.17 in ./venv/lib/python3.9/site-packages (from requests) (2022.12.7)
# Requirement already satisfied: charset-normalizer<4,>=2 in ./venv/lib/python3.9/site-packages (from requests) (3.0.1)
# Requirement already satisfied: urllib3<1.27,>=1.21.1 in ./venv/lib/python3.9/site-packages (from requests) (1.26.14)
# Requirement already satisfied: idna<4,>=2.5 in ./venv/lib/python3.9/site-packages (from requests) (3.4)
- La página para buscar los proyectos que hay en Python que pueden ayudar a tu proyecto es pypi.
- Siempre verifica que estás escribiendo correctamente el nombre del package y que brinda la confianza suficiente para poder usarla en tu proyecto.
- Un buen ejemplo del uso de
requests
lo puedes encontrar al correr el proyecto-shibe.
# Response status code is: 200
['https://cdn.shibe.online/shibes/7d9fb0f9a54108bcd7ebda070844a1dde925c645.jpg']
- Se pueden agragar parámetros al llamado con
requests
:
# First thing we'll do is import the requests library
import requests
# We'll store our base URL here and pass in the count parameter later
api_url = "http://shibe.online/api/shibes"
params = {
"count": 10
}
# Pass those params in with the request.
api_response = requests.get(api_url, params=params)
print(f"Shibe API Response Status Code is: {api_response.status_code}") # should be 200 OK
json_data = api_response.json()
print("Here is a list of URLs for dog pictures:")
for url in json_data:
print(f"\t {url}")
# Shibe API Response Status Code is: 200
# Here is a list of URLs for dog pictures:
# https://cdn.shibe.online/shibes/5e6d5745ba842bf3dfd3c2ede1c756d297724440.jpg
# https://cdn.shibe.online/shibes/9a32be747f49d93b4549bf249dff6b5c1780f1dd.jpg
# https://cdn.shibe.online/shibes/889730d5d62179d1ce6911e2f57d57690f2d60fe.jpg
# https://cdn.shibe.online/shibes/9d349c1deca7da3e177b2a1f2348d88feefac0f2.jpg
# https://cdn.shibe.online/shibes/28d7c372ea7defdb315ef845285d4ac3906ccea4.jpg
# https://cdn.shibe.online/shibes/0881d5d0096b596f3958248646c7a0cdec22f8cb.jpg
# https://cdn.shibe.online/shibes/d9bb81c49c4d6118c26e788852dfa2470089e4f4.jpg
# https://cdn.shibe.online/shibes/abb716ce888cd2ab54342855ec9c11d604c37b4a.jpg
# https://cdn.shibe.online/shibes/03c13496ed1a361e835520d29207e72048b50dca.jpg
# https://cdn.shibe.online/shibes/3b44c4003805679b2427f4093029db1a50fcbd56.jpg
- Es uno de los
Web Frameworks
que nos ofrece Python y que es un todo en uno, contiene todo lo necesario para crear aplicaciones a gran escala. - Es considerado él
Web Framework
para perfeccionistas con losdeadlines
. - Dentro de lo que hay
out of the box
en Django: ORM (Object Relational Model) que hace que trabajar con Bases de Datos sea tan simple como trabajar conPython instances
, incluye unAdmin
que hace fácil manejar tu contenido con formularios y validaciones, también ofrece unUser Authentication
,Template
de lenguaje, protección contraCommon Security Vulnerabilities
y mucho más.
Flask
es unmicroframework
para Python, que permite a los usuarios crear aplicaciones web yAPI
back-end básicas con mucho menos código.Flask
es más fácil de entender y configurar para los principiantes, y es menos obstinado.- El inconveniente es que a medida que desee agregar componentes adicionales a su aplicación, como bases de datos, autenticación y otras capas, deberá usar complementos o paquetes de terceros.
Flask
no los proporciona por default.
- Para hacer un setup de un proyecto Django, se recomienda seguir la guía de Django
python3 -m venv env
source env/bin/activate
(env) python -m pip install -r requirements.txt
(env) python manage.py migrate
(env) python manage.py runserver
(env) python manage.py makemigrations blog
(env) python manage.py migrate
(env) python manage.py shell
(env) python manage.py createsuperuser