viernes, 6 de junio de 2008

List Comprehension

(Material de un Taller que hicimos en la pega)

List Comprehension
==================
List comprehensions provide a concise way to create lists without resorting to use of map(), filter() and/or lambda. The resulting list definition tends often to be clearer than lists built using those constructs. Each list comprehension consists of an expression followed by a for clause, then zero or more for or if clauses. The result will be a list resulting from evaluating the expression in the context of the for and if clauses which follow it. If the expression would evaluate to a tuple, it must be parenthesized.

Simples
=======
>>> [x for x in [1,3,5,7,9]]
[1, 3, 5, 7, 9]

>>> [x for x in range(5)]
[0, 1, 2, 3, 4]

>>> [x for x in range(2,10,2)]
[2, 4, 6, 8]

También se pueden anidar varios ciclos for (Gracias Dorian!)

>>> [ (x,y) for x in [1,2,3] for y in [4,5,6]]
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

Strings funcionan como listas
=============================
>>> [x for x in "Hola compadre"]
['H', 'o', 'l', 'a', ' ', 'c', 'o', 'm', 'p', 'a', 'd', 'r', 'e']



Cálculos:
=========
>>> [x*x for x in range(5)]
[0, 1, 4, 9, 16]


Condiciones:
============
>>> [x*x for x in range(5) if x%2]
[1, 9]
>>> [x*x for x in range(6) if x>3]
[16, 25]


Parseo de archivos:
===================
>>> stream="""Nombre, calorias, cantidad
... perejil, 10, 5
... betarraga, 20, 2
... zanahoria, 30, 10
... chocolate, 1000, 1"""
>>> [line.split(',') for line in stream.split('\n')[1:]]
[['perejil', ' 10', ' 5'], ['betarraga', ' 20', ' 2'], ['zanahoria', ' 30', ' 10'], ['chocolate', ' 1000', ' 1']]

>>> [[e.strip() for e in line.split(',')] for line in stream.split('\n')[1:]]
[['perejil', '10', '5'], ['betarraga', '20', '2'], ['zanahoria', '30', '10'], ['chocolate', '1000', '1']]

>>> [ "Nombre: %s, calorias: %s, cantidad: %s" % tuple([e.strip() for e in line.split(',')]) for line in stream.split('\n')[1:]]
['Nombre: perejil, calorias: 10, cantidad: 5', 'Nombre: betarraga, calorias: 20, cantidad: 2', 'Nombre: zanahoria, calorias: 30, cantidad: 10', 'Nombre: chocolate, calorias: 1000, cantidad: 1']


Capturar solo los números
=========================
>>> values = [[e.strip() for e in line.split(',')] for line in stream.split('\n')[1:]]
>> [ [int(v) for v in line if v.isdigit()] for line in values]
[[10, 5], [20, 2], [30, 10], [1000, 1]]


Pasar los valores formateados
=============================
>>> values_formated = [ ( l[0],int(l[1]),int(l[2]) ) for l in values]
>>> [line for line in values_formated if line[2]>2]
[('perejil', 10, 5), ('zanahoria', 30, 10)]


Suma condicionada: Sumar calorias de todos los elementos con cantidad>2
============================================
>>> sum( [line[1] for line in values_formated if line[2]>2] )
40


Construir strings usando List comprehension
===========================================
Ejemplo para armar una SQL que haga union de varias tablas
>>> " UNION ".join(
... ['SELECT max(%s) as time FROM "%s".%s' % tuple(x[:1]+['SCHEMA_NAME']+x[1:])
... for x in [
... ['field1','table1'],
... ['field2','table2'],
... ['field3','table3'],
... ['field4','table4']
... ]
... ]
... )
'SELECT max(field1) as time FROM "SCHEMA_NAME".table1 UNION SELECT max(field2) as time FROM "SCHEMA_NAME".table2 UNION SELECT max(field3) as time FROM "SCHEMA_NAME".table3 UNION SELECT max(field4) as time FROM "SCHEMA_NAME".table4'



Creación de Dictionary
======================
Ejemplo:
========
Esto no es necesario hacerlo:
d={}
for row in rows:
if d.has_key(row[0]):
d[row[0]].append((row[1], row[2]))
else:
d[row[0]] = [(row[1], row[2])]

Basta con hacer:

>>> rows=[[1,2,3,4,5],[6,7,8,9,0],[11,12,13,14,15]]
>>> d={}
>>> d.update( [ (r[0],(r[1],r[2])) for r in rows] )
>>> d
{1: (2, 3), 11: (12, 13), 6: (7, 8)}



Interseccion, Union, Diferencia entre listas
============================================
>>> A=[1,2,3,4,5]
>>> B=[2,4,6,8]
# Intersecion
>>> [x for x in A if x in B]
[2, 4]
>>> [x for x in B if x in A]
[2, 4]
# Difference
>>> [x for x in B if x not in A]
[6, 8]
>>> [x for x in A if x not in B]
[1, 3, 5]
>>>

Otra forma usando Set
=====================
>>> set(A).intersection(B)
set([2, 4])
>>> list(set(A).intersection(B))
[2, 4]
>>> list(set(B).intersection(A))
[2, 4]
>>> list(set(B).difference(A))
[8, 6]
>>> list(set(A).difference(B))
[1, 3, 5]


Set:
====
A set object is an unordered collection of distinct hashable objects. Common uses include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference. New in version 2.4.


Desafío:
=========

¿Se puede hacer esto con list comprehension?
¿si? ¿no? ¿porqué? ¿cómo?
>>> l=[]
>>> for n in ['Francisco','Richard', 'Luis']:
... for c in ['Fruta','Carne','Verdura']:
... if not(n=='Luis' and c=='Carne'):
... l.append('%s come %s' % (n,c))
...
>>> l
['Francisco come Fruta', 'Francisco come Carne', 'Francisco come Verdura', 'Richard come Fruta', 'Richard come Carne', 'Richard come Verdura', 'Luis come Fruta', 'Luis come Verdura']

lunes, 2 de junio de 2008

Luego de Webprendededor Concepción 2008

Bien motivado me quedé luego de escuchar a todos estos "geaks" (como uno) hablando de emprendimiento, innovación, creatividad, etc...

Noticia en Diario El Sur

Concepción no es un Santiago chico
Webprendedor, con las pilas puestas en Concepción

viernes, 30 de mayo de 2008

lunes, 26 de mayo de 2008

Webprendededor Concepción 2008



Se ven algunas charlas interesantes: Los chicos de Needish, Metrik y el Francotirador, entre otros.

A apoyar este tipo de iniciativas!
En Concepción el día sábado 31 de Mayo

Más encima en el mismo lugar donde estudié...
De allá somos...

import datetime vs from datetime import datetime

Para todos los que desarrollan en Python:

Si van a usar la libraría datetime

Es preferible hacer esto:
import datetime
dtnew = datetime.datetime(2008,5,20)


Que esto:
from datetime import datetime
dtnew = datetime(2008,5,20)


Pues usando el segundo caso, si hacen import de otro modulo que esté
usando datetime, el intérprete se puede marear con los nombres y
pueden haber errores como:
Module object is not callable
TypeError: descriptor 'time' requires a 'datetime.datetime' object but
received a 'int'



Por último si les da demasiada lata escribir datetime muchas veces
pueden hacer algo como esto:
from datetime import datetime as dtime
dtnew = dtime(2008,5,20)

Así no se vuelve a usar el nombre datetime como función y objeto(not
callable) a la vez.

miércoles, 21 de mayo de 2008

Búsquedas por date y datetime

Haciendo un filtro por fechas me di cuenta que no era lo mismo hacer

date1 = datetime.datetime.now().date() (date1 es tipo date)
xxxx.objects.filter(date__lte=date1)

que

date2 = datetime.datetime.now() (date2 es tipo datetime)
xxxx.objects.filter(date__lte=date2)

Obvio, uno de ellos considera horas, minutos y segundos

Así que ojo si hay que decidir un intervalo de días para datos tipo datetime, hay que considerar el día completo:
'2008-05-21 23:59:59'

O sea:
date2= datetime.combine(date1, time(23,59,59))

miércoles, 7 de mayo de 2008

Cómo truncar palabras my largas en la template

{{ object.comments|truncatewords:15|make_list|slice:":80"|join:"" }}
{% if object.comments|truncatewords:15|make_list|slice:":80"|length_is:"80" %} ...{% endif %}

Lo que hice fue pasar el string a una lista, cortarlo, y luego hacer un join para volver a convertirlo string, para dejarlo más bonito: un if que si coincide en largo con el string cortado le agrega los puntos suspensivos ...

La otra opción era armarse una función para el sistema de templates, como aquí:
http://www.djangosnippets.org/snippets/163/

Pero a mí, hacer eso me dió lata :-)