Buenas prácticas en python¶
Virtualenv¶
IPython¶
Zen¶
# output
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
Return multiple values¶
def get_user(id):
# fetch user from database
name = "Fede" # Fake name
birthdate = "01-01-2000" # Fake date
return name, birthdate
name, birthdate = get_user(4)
print(name, birthdate)
One line if¶
Truth value testing¶
true = True
false = False
true_value = "aaa" # truthy
false_value = [] # falsey
none_value = None
# Bad:
if true == True:
print("truthy")
if false == False:
print("falsy")
# Good:
if true:
print("truthy")
if true_value:
print("truthy")
if not false:
print("falsy")
if not false_value:
print("falsy")
if none_value is None:
print(None)
NO Globals¶
Unpacking¶
Merging dict¶
Slicing a list¶
start
, stop
y step
son opcionales.
Si no los completas tendrán los siguientes valores por defecto:
- 0 para
start
- el final de la lista para
end
- 1 para
step
# We can easily create a new list from
# the first two elements of a list:
first_two = [1, 2, 3, 4, 5][0:2]
print(first_two)
# And if we use a step value of 2,
# we can skip over every second number
# like this:
steps = [1, 2, 3, 4, 5][0:5:2]
print(steps)
# This works on strings too. In Python,
# you can treat a string like a list of
# letters:
mystring = "abcdefdn nimt"[::2]
print(mystring)
Enumerate¶
# Bad
numbers = [2,4,6,8,10]
i = 0
for number in numbers:
print(f"Item: #{number:02} at: {i}")
i += 1
# Good
numbers = [2,4,6,8,10]
for i, number in enumerate(numbers):
print(f"Item: #{number:02} at: {i}")
Zip¶
numbers = [1, 2, 3]
words = ['one', 'two', 'three']
numbers_and_words = zip(numbers, words)
print(list(numbers_and_words))
# zip(numbers, words, strict=True) Probar!
Map¶
Map se utiliza generalmente cuando quiero aplicarle alguna transformación a cada elemento de la lista, pero no alterar la cantidad de elementos.
# Convert a string representation of
# a number into a list of ints.
list_of_ints = list(map(int, "1234567"))
print(list_of_ints)
Filter¶
El filter se utiliza cuando quiero generalmente modificar la cantidad de elementos de un iterable, pero no transformar cada elemento.
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
filtered = filter(lambda x: x%3 == 0, numbers)
print(list(filtered))
numbers = [1, None, 2, 3, 4, None, 5, 6, 7, 8, 9]
filtered = filter(bool, numbers)
print(list(filtered))
Reduce¶
Se puede utilizar en distintos casos:
- Quiero sumarizar valores de un iterable
- Quiero generar un iterable bastante distinto en forma partiendo de otro
Se recomienda no utilizarlo cuando se podría haber usado un filter o un map
from functools import reduce
numbers = (1, 4, 8, 18, 22)
print("a:", reduce(lambda acc, number: acc + number, numbers))
print("b:", reduce(lambda acc, number: number, numbers))
print("c:", reduce(lambda acc, number: acc, numbers))
# using reduce with initializer = 3
print("d:", reduce(lambda acc, number: acc + number, numbers, 3))
from functools import reduce
list_of_invitees = [
{"email": "alex@example.com", "name": "Alex", "status": "attending"},
{"email": "brian@example.com", "name": "Brian", "status": "declined"},
{"email": "carol@example.com", "name": "Carol", "status": "pending"},
{"email": "derek@example.com", "name": "Derek", "status": "attending"},
{"email": "ellen@example.com", "name": "Ellen", "status": "attending"}
]
def invitee(acc, invitee):
acc[invitee["name"]] = invitee["status"]
return acc
result = reduce(invitee, list_of_invitees, {})
print(result)
# output
{'Alex': 'attending', 'Brian': 'declined', 'Carol': 'pending', 'Derek': 'attending', 'Ellen': 'attending'}
List comprehension¶
Esta expresión nos permite hacer prácticamente lo mismo que un filter y un map al mismo tiempo.
squares = []
for x in range(10):
squares.append(x**2)
print("a:", squares)
# --
squares = [x**2 for x in range(10)]
print("b:", squares)
def some_function(a):
return (a + 5) / 2
my_formula = [some_function(i) for i in range(10)]
print(my_formula)
Generators¶
Todas las funciones que vimos anteriormente son eficientes. Lo son porque lo que terminan devolviendo internamente son generadores. Los generadores nos permiten devolver parcialmente elementos en una iteración si tener que procesar toda la estructura.
Iterar hasta numeros muy grandes¶
def g_range(start, end):
n = start
while True:
yield n
n += 1
if n == end:
break
gr = g_range(0, 100_000_000)
Iterar infitinamente¶
Pipeline de generadores¶
def fibonacci_numbers(nums):
x, y = 0, 1
for _ in range(nums):
x, y = y, x+y
yield x
def square(nums):
for num in nums:
yield num**2
print(sum(square(fibonacci_numbers(10))))
Data classes¶
from dataclasses import dataclass
@dataclass
class Card:
rank: str
suit: str
card = Card("Q", "hearts")
print("Equals?", card == card)
print("Rank:", card.rank)
print("Card:", card)
Ejemplo para usar en el juego¶
import PySimpleGUI as sg
from dataclasses import dataclass, field
@dataclass
class Event():
name: str
values: dict = field(default_factory=dict)
sg.theme('DarkAmber') # Keep things interesting for your users
layout = [[sg.Text('Persistent window')],
[sg.Input(key="-AGE-")],
[sg.Input(key="-TEXT-")],
[sg.Button('Read'), sg.Exit()]]
window = sg.Window('Window that stays open', layout)
while True: # The Event Loop
event = Event(*window.read())
print(event)
match event:
case Event(name='Read', values={"-AGE-": str(value)}) if int(value) < 18:
print("ES MENOR de edad!")
case Event(name='Read', values={"-NAME-": str(value)}):
print(f"READ: {value}")
case Event(name='Exit'):
print("EXIT")
break
window.close()