Slide 1

Slide 1 text

Python the good parts

Slide 2

Slide 2 text

Miguel Araujo @maraujop

Slide 3

Slide 3 text

import this

Slide 4

Slide 4 text

El zen de Python - PEP20 •  Explícito es mejor que implícito •  Plano es mejor que anidado •  La legibilidad cuenta •  Debería haber una-- y preferiblamente solo una-- forma obvia de hacer algo.

Slide 5

Slide 5 text

Pythonic / Pythonico

Slide 6

Slide 6 text

No pythonico names = ['Juan', 'Pedro', 'Isabel'] i = 0 while (i < len(names)): print names[i] i += 1

Slide 7

Slide 7 text

No pythonico names = ["Juan", "Pedro", "Isabel"] for i in range(len(names)): print names[i]

Slide 8

Slide 8 text

Pythonico names = ["Juan", "Pedro", "Isabel"] for name in names: print name

Slide 9

Slide 9 text

No pythonico if name == "Juan" or name == "Pedro" or name == "Maria": Pythonico if name in ("Juan", "Pedro", "Maria"):

Slide 10

Slide 10 text

No pythonico numbers = [1, 2, 3, 4] total = 0 for number in numbers: total += number Pythonico total = sum(numbers)

Slide 11

Slide 11 text

Coding style

Slide 12

Slide 12 text

Utiliza siempre un coding style

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

Coding style - PEP8 Code is read much more often than is written Guido Van Rossum “

Slide 15

Slide 15 text

Coding style - PEP8 •  Indentar con 4 espacios •  Columnas de 80 ó 100 caracteres •  Separar clases y funciones de primer nivel por 2 espacios •  Imports en lineas diferentes import sys import os

Slide 16

Slide 16 text

Coding style - Espacios •  Sí: spam(ham[1], {eggs: 2}) No: spam( ham[ 1 ], { eggs: 2 } ) •  Sí: x, y = 4, 5 No: x , y = 4 , 5 •  Sí: def publish(message=None) No:def publish(message = None)

Slide 17

Slide 17 text

Coding style - Espacios Sí: x = 1 long_variable = 4 No: x = 1 long_variable = 4

Slide 18

Slide 18 text

people = { "nombre": "Juan", "nombre": "Pedro", "nombre": "Maria" } people = { "nombre": "Juan", "nombre": "Pedro", "nombre": "Maria" } Coding style - indentar

Slide 19

Slide 19 text

CONSTANTS def function_names_in_lowercase class CapWords def method(self, ...): def _private_method(self, ...): def class_method(cls, ...): Coding style - nomenclatura

Slide 20

Slide 20 text

def search(number_of_files=0): if (number_of_files > 0): [...] return (number_of_files, files_found) Coding style - paréntesis

Slide 21

Slide 21 text

Coding style - Herramientas •  pep8 •  pylint

Slide 22

Slide 22 text

Patrones

Slide 23

Slide 23 text

Expansión de listas def print_args(*args): for arg in args: print arg random_list = [1, "hi", [2, 3]] print_args(*random_list)

Slide 24

Slide 24 text

Expansión de diccionarios def search_feed(num_messages, min_favs, user_handle): [...] search_feed(num_messages=20, min_favs=5, user_handle='maraujop') search_feed(**{ 'num_messages': 20, 'min_favs': 5, 'user_handle': 'maraujop' })

Slide 25

Slide 25 text

Posicional vs Keyword search_feed(40, 5, 'maraujop') search_feed(num_messages=40, min_favs=5, user_handle='maraujop')

Slide 26

Slide 26 text

Decoradores - PEP 318 from decorator import decorator @decorator def trace(f, *args, **kwargs): print "calling %s with args %s, %s" % (f, args, kwargs) return f(*args, **kwargs) @trace def search_feed(num_messages, min_favs, user_handle): print "Searching feed..."

Slide 27

Slide 27 text

Decoradores search_feed(num_messages=20, min_favs=5, user_handle="maraujop") calling with args (20, 5, 'maraujop'), {} Searching feed...

Slide 28

Slide 28 text

setattr / hasattr person = Person() variable_name = 'age' value = 26 setattr(person, variable_name, value) hasattr(person, variable_name) hasattr(person, 'age')

Slide 29

Slide 29 text

isinstance / issubclass isinstance(2, int) True isinstance(2, float) False value = {'name': "Juan"} isinstance(value, dict)

Slide 30

Slide 30 text

Clases base abstractas import abc class Example: __metaclass__ = abc.ABCMeta @abc.abstractmethod def abstract_method(self): pass @abc.abstractproperty def abstract_property(self): pass

Slide 31

Slide 31 text

Métodos magicos class Agenda: def __init__(self, description): self.people = [ ] self.description = description def __getattr__(self, name): return object.__getattribute__(self.people, name) office = Agenda('People in the office') office.append({'name': 'Miguel', 'age': 26}) print office.description print [person['age'] for person in office]

Slide 32

Slide 32 text

Métodos magicos class Agenda: def __len__(self): return len(self.people) def __contains__(self, item): return item.lower() in [person['name'].lower() for person in self.people] print len(office) for name in ('Miguel', 'Juan'): if name in office: print "%s in office" % name

Slide 33

Slide 33 text

Métodos magicos http://www.rafekettler.com/magicmethods.html

Slide 34

Slide 34 text

Antipatrones

Slide 35

Slide 35 text

__init__.py getters / setters import *

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

Idioms

Slide 38

Slide 38 text

Iterando una colección y sus índices for i, name in enumerate(names): PEP 279

Slide 39

Slide 39 text

Iterando varias colecciones names = ["Juan", "Pedro", "Isabel", "Maria"] numbers = [23, 31, 18] for name, number in zip(names, numbers): print "name %s number %s" % (name, number) [('Juan', 23), ('Pedro', 31), ('Isabel', 18)]

Slide 40

Slide 40 text

Crear diccionarios names = ["Miguel", "Juan", "Pedro"] ages = [21, 22, 34] zip(names, ages) [('Miguel', 21), ('Juan', 22), ('Pedro', 34)] dict(zip(names, ages)) {'Juan': 22, 'Miguel': 21, 'Pedro': 34}

Slide 41

Slide 41 text

Contar con diccionarios from collections import defaultdict message = "Bienvenidos a la primera PyCon España, la primera" count = defaultdict(int) for word in message.split(): count[word] += 1

Slide 42

Slide 42 text

Contar con Counter from collections import Counter message = "Bienvenidos a la primera PyCon España, la primera" count = Counter(message.split())

Slide 43

Slide 43 text

Funcional

Slide 44

Slide 44 text

Funcional •  Ideal para trabajar estructuras de datos •  No debe abusarse de ella, ni obsesionarse con ella

Slide 45

Slide 45 text

Ordenar lista de diccionarios people = [ {'edad': 14, 'nombre': 'Juan'}, {'edad': 26, 'nombre': 'Miguel'}, {'edad': 30, 'nombre': 'Aria'} ] sorted(people, key=lambda person: person['edad'])

Slide 46

Slide 46 text

Ordenar lista de diccionarios •  Las lambdas son lentas, itemgetter está implementado en C •  Para muchos más fácil de leer y más corto from operator import itemgetter sorted(people, key=itemgetter('edad'))

Slide 47

Slide 47 text

List comprehensions - PEP 202 •  Las llamadas a función son cacheadas, son rápidas words = ["hola", "que", "tal"] [word.upper() for word in words]

Slide 48

Slide 48 text

filter people = [ {'edad': 24, 'nombre': 'Saul'}, {'edad': 22, 'nombre': 'Juan'} ] filter(lambda person: person['edad'] > 22, people) [{'edad': 24, 'nombre': 'Saul'}]

Slide 49

Slide 49 text

Aplanando estructuras de datos from itertools import chain list(chain.from_iterable([ [{"nombre": "Jorge"}, {"nombre": "Pedro"}], [{"nombre": "Jesus"}] ])) [{'nombre': 'Jorge'}, {'nombre': 'Pedro'}, {'nombre': 'Jesus'}]

Slide 50

Slide 50 text

Python rocks

Slide 51

Slide 51 text

Python rocks •  Un ecosistema robusto, maduro y de calidad •  Tests y documentación •  Entornos virtuales y pip

Slide 52

Slide 52 text

HTTP

Slide 53

Slide 53 text

Python requests import requests requests.get("http://example.com", params={'search_term': "foo"}) requests.post("http://example.com", data={'new_password': "bar"})

Slide 54

Slide 54 text

Python requests •  rauth OAuth 1.0/a, 2.0, y Ofly •  HTTPretty Mockear urls y sus respuestas •  httpie un cURL para humanos •  Muchos bindings para APIs

Slide 55

Slide 55 text

Fechas y tiempos

Slide 56

Slide 56 text

pytz from datetime import datetime import pytz now = datetime.utcnow() datetime.datetime(2013, 11, 17, 14, 13, 51, 641900) now = now.replace(tzinfo=pytz.utc) datetime.datetime(2013, 11, 17, 14, 13, 51, 641900, tzinfo=) now.astimezone(pytz.timezone("Europe/Madrid")) datetime.datetime(2013, 11, 17, 15, 13, 51, 641900, tzinfo=)

Slide 57

Slide 57 text

python-dateutil import calendar from dateutil.relativedelta import relativedelta now + relativedelta(month=1, day=23) now + relativedelta(months=-1, days=5) now + relativedelta(weekday=calendar.FRIDAY)

Slide 58

Slide 58 text

Bases de datos

Slide 59

Slide 59 text

ORMs •  SQLAlchemy El ORM más potente de Python y mucho más •  peewee Similar al ORM de Django's pero con un API más consistente •  Django ORM

Slide 60

Slide 60 text

Más!!

Slide 61

Slide 61 text

Más •  Pandas Librería de análisis de datos •  pattern Data mining •  Boto Interfaz para AWS •  Pillow Librería para manejo de imágenes •  Path Manejo de rutas y ficheros •  Docopt Parser de línea de comandos •  bleach Sanitizador de HTML •  Jinja Motor de plantillas

Slide 62

Slide 62 text

APIs humanas != APIs buenas

Slide 63

Slide 63 text

Simplificar la mecánica habitual al máximo

Slide 64

Slide 64 text

Ejemplo nltk Natural Language Tool Kit tokens = nltk.word_tokenize("I like eating chocolate with milk") tagged = nltk.pos_tag(tokens) [(u'I', u'PRP'), (u'like', u'VB'), (u'eating', u'VBG'), (u'chocolate', u'NN'), (u'with', u'IN'), (u'milk', u'NN')]

Slide 65

Slide 65 text

Ejemplo TextBlob API sencilla para procesar datos textuales blob = TextBlob("I like eating chocolate with milk") blob.tags [(u'I', u'PRP'), (u'like', u'VB'), (u'eating', u'VBG'), (u'chocolate', u'NN'), (u'with', u'IN'), (u'milk', u'NN')]

Slide 66

Slide 66 text

Debe tener conceptos de alto nivel

Slide 67

Slide 67 text

Ejemplo OpenCV import cv2 import cv2.cv as cv def camshift_tracking(img1, img2, bb): hsv = cv2.cvtColor(img1, cv.CV_BGR2HSV) mask = cv2.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.))) x0, y0, w, h = bb x1 = x0 + w -1 y1 = y0 + h -1 hsv_roi = hsv[y0:y1, x0:x1] mask_roi = mask[y0:y1, x0:x1] hist = cv2.calcHist( [hsv_roi], [0], mask_roi, [16], [0, 180] ) cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX); hist_flat = hist.reshape(-1) prob = cv2.calcBackProject([hsv,cv2.cvtColor(img2, cv.CV_BGR2HSV)], [0], hist_flat, [0, 180], 1) prob &= mask term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 ) new_ellipse, track_window = cv2.CamShift(prob, bb, term_crit) return track_window

Slide 68

Slide 68 text

Ejemplo SimpleCV camera, display = Camera(), Display() bounding_box = (100, 200, 100, 100) track_set = [ ] previous = camera.getImage() while display.isNotDone(): frame = camera.getImage() track_set = frame.track('camshift', track_set, previous, bounding_box) track_set.drawBB() previous = frame frame.save(display)

Slide 69

Slide 69 text

Poder usarse sin conocer detalles internos

Slide 70

Slide 70 text

Ejemplo urllib2 import urllib2 gh_url = 'https://api.github.com' req = urllib2.Request(gh_url) password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() password_manager.add_password(None, gh_url, 'user', 'pass') auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) opener = urllib2.build_opener(auth_manager) urllib2.install_opener(opener) handler = urllib2.urlopen(req) print handler.getcode() print handler.headers.getheader('content-type')

Slide 71

Slide 71 text

Ejemplo requests import requests r = requests.get('https://api.github.com', auth=('user', 'pass')) print r.status_code print r.headers['content-type']

Slide 72

Slide 72 text

Debe generar código mantenible

Slide 73

Slide 73 text

Ejemplo argparse - PEP 389 if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--run', dest='action', help='argparse example') args = parser.parse_args() if args.action == 'update': print "Updating..." elif args.action == 'watch': print "Watch..."

Slide 74

Slide 74 text

""" Usage: example.py run (update|watch) example.py -h | --help example.py --version Options: -h --help Show help message. --version Show version. """ Ejemplo docopt if __name__ == '__main__': args = docopt(__doc__, version='1.0') if args['update']: print "Updating..." elif args['watch']: print "Watch..."

Slide 75

Slide 75 text

Python moderno

Slide 76

Slide 76 text

Python moderno •  Python 2.0 en el año 2000 •  PEPs •  Recolector de basura / soporte de Unicode •  PEP 1 -- PEP Purpose and Guidelines

Slide 77

Slide 77 text

Python 3.4

Slide 78

Slide 78 text

Gracias, ¿preguntas?