SlideShare a Scribd company logo
1 of 55
Download to read offline
The  unknown  
COLLECTIONS	
module	

{

“event”:      “PyCon  ES  2013”	
“author”:  “Pablo  Enfedaque”	
“twi2er”:  “pablitoev56”
Today  we  are  going  to  talk  about  the  
(unknown)  collections  module	
	
And  also  about  built-­‐‑in  containers	

Welcome!	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
“This  module  implements  
specialized  container  datatypes  
providing  alternatives  to  Python’s  
general  purpose  built-­‐‑in  containers,  
dict,  list,  set,  and  tuple”	

The  collections  module	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
Let’s  start  with  Python’s  most  used  
container	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
Yes,  that’s  dict	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> d = {'a': 1, 'b': 2, 'c': 3}	
	
>>> d['b']	
2	
	
>>> d['d'] = 4	
	
>>> d	
{'d': 4, 'b': 2, 'c': 3, 'a': 1}	
	
>>> d['e']	
Traceback (most recent call last):	
File "<stdin>", line 1, in <module>	
KeyError: 'e'	
	
>>> print(d.get('e'))	
None	
	
>>> d.get('e', 5)	
5	

dict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
OPERATION	

AVERAGE	
 AMORTIZED  WORST	

Get  item    d['b']	

O(1)	

O(n)	

Set  item      d['d'] = 4	

O(1)*	

O(n)	

Delete  item    del d['b']	

O(1)	

O(n)	

Copy    new_d = dict(d)	

O(n)	

O(N)	

Iteration    for k in d:	

O(n)	

O(N)	

> 

Internally  implemented  with  an  optimised  hash  map	

> 

*:  Amortized  cost.  Individual  ops  may  be  really  slow	

> 

N:  Maximum  size  the  container  ever  achieved	

dict  performance	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
And  what  about  set?	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> vowels = {'a', 'e', 'i', 'o', 'u'}	
>>> letters = set(['a', 'b', 'c', 'd', 'e'])	
	
>>> vowels – letters	
{'i', 'o', 'u’}	
>>> vowels & letters	
{'a', 'e’}	
>>> vowels | letters	
{'u', 'i', 'o', 'c', 'b', 'a', 'e', 'd’}	
>>> vowels ^ letters	
{'u', 'i', 'o', 'c', 'b', 'd'}	
	
>>> 'b' in letters	
True	
	
>>> letters.add('a')	
>>> letters	
{'c', 'b', 'a', 'e', 'd'}	
	
>>> letters.update(['d', 'e', 'f', 'g'])	
>>> letters	
{'c', 'b', 'a', 'g', 'f', 'e', 'd'}	

set	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
OPERATION	

AVERAGE	

AMORTIZED  WORST	

Check  item        'b' in s1	

O(1)	

O(n)	

Union                                  s1 | s2	

O(len(s1)  +  len(s2))	

Intersection              s1 & s2	
 O(min(len(s1),  len(s2)))	
Difference                    s1 – s2	

O(len(s1))	

Symmetric  diff    s1 ^ s2  	

O(len(s1))	

O(len(s1)  *  len(s2))	

> 
> 

O(len(s1)  *  len(s2))	

Implementation  very  similar  to  dicts  (hash  map)	
Also  has  in-­‐‑place  modification  methods  (its  average  
cost  depends  on  s2)	

set  performance	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
A  bit  boring,  isn’t  it?	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
Let'ʹs  do  something  more  appealing	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
txt = """El desconocido módulo Collections	
Todo el mundo conoce los tipos básicos de Python y sus
contenedores más comunes (list, tuple, dict y set). En cambio,
poca gente sabe que para implementar una cola debería utilizar
un deque, que con un defaultdict su código quedaría más limpio y
sería un poco más eficiente o que podría utilizar namedtuples en
lugar de crear nuevas clases. En esta charla repasaremos las
estructuras del módulo collections de la librería estándar:
namedtuple, deque, Counter, OrderedDict y defaultdict. Veremos
su funcionalidad, particularidades y casos prácticos de uso.	
	
Pablo Enfedaque Vidal	
Trabajo como R&D SW Engineer en Telefónica PDI en Barcelona, y
desde hace más de 5 años casi exclusivamente con Python, un
lenguaje que me encanta"""	

During  the  talk  we  will  use  this  str	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> initials = {}	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
if word[0] in initials:	
initials[word[0]].append(word)	
else:	
initials[word[0]] = [word, ]	
	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
>>> classify_words(txt)	
y ['y', 'y', 'y', 'y', 'y', 'y']	
s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw']	
r ['repasaremos', 'r&d']	
q ['que', 'que', 'quedaría', 'que', 'que']	
...	

Let’s  classify  words	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> initials = {}	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
if word[0] in initials:	
initials[word[0]].append(word)	
else:	
initials[word[0]] = [word, ]	
	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
>>> classify_words(txt)	
y ['y', 'y', 'y', 'y', 'y', 'y']	
s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw']	
r ['repasaremos', 'r&d']	
q ['que', 'que', 'quedaría', 'que', 'que']	
...	

Does  it  look  pythonic?	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> initials = {}	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
initials.setdefault(word[0], []).append(word)	
	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
	
	
	
>>> classify_words(txt)	
y ['y', 'y', 'y', 'y', 'y', 'y']	
s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw']	
r ['repasaremos', 'r&d']	
q ['que', 'que', 'quedaría', 'que', 'que']	
...	

What  about  now?	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import defaultdict	
	
>>> initials = defaultdict(list)	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
initials[word[0]].append(word)	
	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
	
	
	
>>> classify_words(txt)	
y ['y', 'y', 'y', 'y', 'y', 'y']	
s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw']	
r ['repasaremos', 'r&d']	
q ['que', 'que', 'quedaría', 'que', 'que']	
...	

collections.defaultdict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import defaultdict	
	
>>> initials = defaultdict(list)	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
initials[word[0]].append(word)	
	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
>>> initials.default_factory	
<class 'list'>	
	
>>> classify_words(txt)	
y ['y', 'y', 'y', 'y', 'y', 'y']	
s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw']	
r ['repasaremos', 'r&d']	
q ['que', 'que', 'quedaría', 'que', 'que']	
...	

collections.defaultdict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
> 

defaultdict  is  a  subclass  of  the  built-­‐‑in  dict  class	

> 

The  first  argument  provides  the  initial  value  for  the  
default_factory  a2ribute  (it  defaults  to  None)	

> 

All  remaining  arguments  are  treated  the  same	

> 

It  also  overrides  the  __missing__  method  to  call  the  
default_factory  when  an  key  is  not  found	

> 

default_factory  may  raise  an  exception  (e.g.  KeyError)	

> 

Since  Python  2.5	

collections.defaultdict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
Let’s  continue  classifying  words	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
class WordsByInitial():	
"Holds initial letter and a set and a list of words"	
def __init__(self, letter):	
self.letter = letter	
self.words = []	
self.unique_words = set()	
	
def append(self, word):	
self.words.append(word)	
self.unique_words.add(word)	
	
def __str__(self):	
return "<{}: {} {}>".format(self.letter,	
self.unique_words,	
self.words)	
>>> a_words = WordsByInitial('a')	
	
>>> a_words.append('ahora')	
>>> a_words.append('adios')	
>>> a_words.append('ahora')	
	
>>> print(a_words)	
<a: {'adios', 'ahora'} ['ahora', 'adios', 'ahora']>	

Now  we  have  this  custom  class	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
What  if  we  want  to  use  our  class  with  
defaultdict?	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
class WordsByInitial():	
"Holds initial letter and set and list of words"	
def __init__(self, letter):	
self.letter = letter	
self.words = []	
self.unique_words = set()	
	
def append(self, word):	
self.words.append(word)	
self.unique_words.add(word)	
	
def __str__(self):	
return "<{}: {} {}>".format(self.letter,	
self.unique_words,	
self.words)	
>>> a_words = WordsByInitial('a')	
	
>>> a_words.append('ahora')	
>>> a_words.append('adios')	
>>> a_words.append('ahora')	
	
>>> print(a_words)	
<a: {'adios', 'ahora'} ['ahora', 'adios', 'ahora']>	

How  do  we  get  the  le2er?	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
What  if  we  want  the  default_factory  
to  receive  the  missing  key?	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
class WordsDict(dict):	
def __missing__(self, key):	
res = self[key] = WordsByInitial(key)	
return res	
	
initials = WordsDict()	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
initials[word[0]].append(word)	
	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
>>> classify_words(txt)	
y <y: {'y'} ['y', 'y', 'y', 'y', 'y', 'y']>	
s <s: {'sería', 'sus', 'set).', 'sabe', 'sw', 'su'} ['sus’...	
r <r: {'r&d', 'repasaremos'} ['repasaremos', 'r&d']>	
q <q: {'quedaría', 'que'} ['que', 'que', 'quedaría', 'que’...	
...	

Time  to  code  our  custom  dict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
class WordsDict(dict):	
def __missing__(self, key):	
res = self[key] = WordsByInitial(key)	
return res	
	
initials = WordsDict()	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
initials[word[0]].append(word)	
	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
>>> classify_words(txt)	
y <y: {'y'} ['y', 'y', 'y', 'y', 'y', 'y']>	
s <s: {'sería', 'sus', 'set).', 'sabe', 'sw', 'su'} ['sus’...	
r <r: {'r&d', 'repasaremos'} ['repasaremos', 'r&d']>	
q <q: {'quedaría', 'que'} ['que', 'que', 'quedaría', 'que’...	
...	

Subclass  overriding  __missing__	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
Let'ʹs  move  on  to  something  different	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import defaultdict	
	
def wordcount(s):	
wc = defaultdict(int)	
for word in s.split():	
wc[word] += 1	
return wc	
	
>>> wc = wordcount(txt)	
	
>>> for letter, num in wc.items():	
print(letter, num)	
del 1	
implementar 1	
exclusivamente 1	
más 4	
y 6	
...	
	
>>> sorted(wc.items(), reverse=True, key=lambda x: x[1])[:3]	
[('y', 6), ('de', 5), ('más', 4)]	

Let’s  count  words	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import Counter	
	
def wordcount(s):	
return Counter(s.split())	
	
	
	
	
>>> wc = wordcount(txt)	
	
>>> for letter, num in wc.items():	
print(letter, num)	
del 1	
implementar 1	
exclusivamente 1	
más 4	
y 6	
...	
	
>>> wc.most_common(3)	
[('y', 6), ('de', 5), ('más', 4)]	

collections.Counter	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import Counter	
	
def wordcount(s):	
return Counter(s.split())	
	
	
	
	
>>> wc = wordcount(txt)	
	
>>> for letter, num in wc.items():	
print(letter, num)	
del 1	
implementar 1	
exclusivamente 1	
más 4	
y 6	
...	
	
>>> wc.most_common(3)	
[('y', 6), ('de', 5), ('más', 4)]	

collections.Counter	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> c1 = Counter(a=3, e=2, i=-1, o=5)	
>>> c2 = Counter(a=1, b=1, c=1, d=1, e=1)	
	
>>> c1['u']	
0	
	
>>> c1.most_common(2)	
[('o', 5), ('a', 3)]	
	
>>> list(c1.elements())	
['o', 'o', 'o', 'o', 'o', 'a', 'a', 'a', 'e', 'e']	
	
>>> c1.subtract(c2)	
>>> c1	
Counter({'o': 5, 'a': 2, 'e': 1, 'c': -1, 'b': -1, 'd': -1, 'i': -1})	
	
>>> c1.update(['b', 'c', 'd'])	
>>> c1	
Counter({'o': 5, 'a': 2, 'e': 1, 'c': 0, 'b': 0, 'd': 0, 'i': -1})	

More  on  collections.Counter	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> c1 = Counter(a=3,
>>> c2 = Counter(a=1,
	
>>> c1 + c2	
Counter({'o': 5, 'a':
	
>>> c1 - c2	
Counter({'o': 5, 'a':
	
>>> c1 & c2	
Counter({'a': 1, 'e':
	
>>> c1 | c2	
Counter({'o': 5, 'a':
	
>>> +c1	
Counter({'o': 5, 'a':
	
>>> -c1	
Counter({'i': 1})	

e=2, i=-1, o=5)	
b=1, c=1, d=1, e=1)	
3, 'e': 2, 'c': 1, 'b': 1, 'd': 1})	
1})	
1})	
2, 'c': 1, 'b': 1, 'e': 1, 'd': 1})	
2, 'e': 1})	

More  on  collections.Counter	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
> 

Counter  is  a  dict  subclass  for  counting  hashable  objects	

> 

dict  interface  but  they  return  0  instead  of  KeyError	

> 

Three  additional  methods:  most_common,  elements,  
subtract	

> 

update  method  has  been  overriden	

> 

Support  for  mathematical  operators:  +,  -­‐‑,  &,  |	

> 

Since  Python  2.7	

collections.Counter	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
Let'ʹs  go  back  to  words  classification	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import defaultdict	
	
>>> initials = defaultdict(list)	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
initials[word[0]].append(word)	
	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
	
	
	
>>> classify_words(txt)	
y ['y', 'y', 'y', 'y', 'y', 'y']	
s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw']	
r ['repasaremos', 'r&d']	
q ['que', 'que', 'quedaría', 'que', 'que']	
...	

Classify  words  with  defaultdict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
What  if  we  only  want  to  keep  the	
last  three  words  for  each  le2er?	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import defaultdict, deque	
	
>>> initials = defaultdict(lambda: deque(maxlen=3))	
	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
initials[word[0]].append(word)	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
	
	
	
>>> classify_words(txt)	
y deque(['y', 'y', 'y'], maxlen=3)	
s deque(['sería', 'su', 'sw'], maxlen=3)	
r deque(['repasaremos', 'r&d'], maxlen=3)	
q deque(['quedaría', 'que', 'que'], maxlen=3)	
...	

collections.deque	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import defaultdict, deque	
	
>>> initials = defaultdict(lambda: deque(maxlen=3))	
	
	
def classify_words(text):	
for word in text.split():	
word = word.lower()	
initials[word[0]].append(word)	
for letter, letter_words in initials.items():	
print(letter, letter_words)	
	
	
	
	
>>> classify_words(txt)	
y deque(['y', 'y', 'y'], maxlen=3)	
s deque(['sería', 'su', 'sw'], maxlen=3)	
r deque(['repasaremos', 'r&d'], maxlen=3)	
q deque(['quedaría', 'que', 'que'], maxlen=3)	
...	

collections.deque	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> d = deque(maxlen=5)	
	
>>> d.extend(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])	
>>> d	
deque(['d', 'e', 'f', 'g', 'h'], maxlen=5)	
	
>>> d.append('i')	
>>> d	
deque(['e', 'f', 'g', 'h', 'i'], maxlen=5)	
	
>>> d.appendleft('Z')	
>>> d	
deque(['Z', 'e', 'f', 'g', 'h'], maxlen=5)	
	
>>> d.rotate(3)	
>>> d	
deque(['f', 'g', 'h', 'Z', 'e'], maxlen=5)	
	
>>> d.popleft()	
'f’	
	
>>> d	
deque(['g', 'h', 'Z', 'e'], maxlen=5)	

More  on  collections.deque	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
OPERATION	

AVERAGE	
 AMORTIZED  WORST	

append('b’)	

O(1)	

O(1)	

appendleft('b’)	

O(1)	

O(1)	

pop()	

O(1)	

O(1)	

popleft()	

O(1)	

O(1)	

extend(iterable)	

O(k)	

O(k)	

extendleft(iterable)	

O(k)	

O(k)	

rotate()	

O(k)	

O(k)	

remove('b’)	

O(n)	

O(n)	

> 

Represented  internally  as  a  doubly  linked  list	

> 

Ideal  to  implement  queues  (FIFO)	

> 

Since  Python  2.4  	

deque  performance	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
OPERATION	

AVERAGE	
 AMORTIZED  WORST	

append('b’)	

O(1)*	

O(1)*	

insert(index, 'b’)	

O(n)	

O(n)	

Get  item    d[4]	

O(1)	

O(1)	

Set  item      d[4] = 'd'	

O(1)	

O(1)	

Delete  item    del d[4]	

O(n)	

O(n)	

extend(iterable)	

O(k)*	

O(k)*	

Check  item    'b' in list	

O(n)	

O(n)	

O(n  log  n)	

O(n  log  n)	

Sort	
> 

Represented  internally  as  an  array	

> 

*:  Amortized  cost.  Individual  ops  may  be  really  slow	

> 

Ideal  to  implement  stacks  (LIFO)	

list  performance	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
Let’s  move  to  a  different  example	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
CACHE = {}	
	
	
def set_key(key, value):	
"Set a key value"	
CACHE[key] = value	
	
	
	
def get_key(key):	
"Retrieve a key value from the cache, or None if not found"	
return CACHE.get(key, None)	
	
	
>>> set_key("my_key", "the_value”)	
>>> print(get_key("my_key"))	
the_value	
	
>>> print(get_key("not_found_key"))	
None	

Let’s  implement  a  SW  cache	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
What  if  we  want  to  limit  its  size?	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import OrderedDict	
	
CACHE = OrderedDict()	
MAX_SIZE = 3	
	
def set_key(key, value):	
"Set a key value, removing oldest key if MAX_SIZE exceeded"	
CACHE[key] = value	
if len(CACHE) > MAX_SIZE:	
CACHE.popitem(last=False)	
	
def get_key(key):	
"Retrieve a key value from the cache, or None if not found"	
return CACHE.get(key, None)	
	
>>> set_key("my_key", "the_value”)	
>>> print(get_key("my_key"))	
the_value	
	
>>> print(get_key("not_found_key"))	
None	
>>> CACHE	
OrderedDict([('c', 3), ('d', 4), ('e', 5)])	

collections.OrderedDict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
from collections import OrderedDict	
	
CACHE = OrderedDict()	
MAX_SIZE = 3	
	
def set_key(key, value):	
"Set a key value, removing oldest key if MAX_SIZE exceeded"	
CACHE[key] = value	
if len(CACHE) > MAX_SIZE:	
CACHE.popitem(last=False)	
	
def get_key(key):	
"Retrieve a key value from the cache, or None if not found"	
return CACHE.get(key, None)	
	
>>> set_key("my_key", "the_value”)	
>>> print(get_key("my_key"))	
the_value	
	
>>> print(get_key("not_found_key"))	
None	
>>> CACHE	
OrderedDict([('c', 3), ('d', 4), ('e', 5)])	

collections.OrderedDict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> d = OrderedDict()	
>>> d.update([(‘a', 1), (‘e', 2), ('i', 3), ('o', 4), ('u', 5)])	
>>> d	
OrderedDict([('a', 1), ('e', 2), ('i', 3), ('o', 4), ('u', 5)])	
	
>>> d['i'] = 0	
>>> list(d.items())	
[('a', 1), ('e', 2), ('i', 0), ('o', 4), ('u', 5)]	
	
>>> d.popitem()	
('u', 5)	
>>> d.popitem(last=False)	
('a', 1)	
>>> d	
OrderedDict([('e', 2), ('i', 0), ('o', 4)])	
	
>>> d.move_to_end('i')	
>>> d	
OrderedDict([('e', 2), ('o', 4), ('i', 0)])	
>>> d.move_to_end('i', last=False)	
>>> d	
OrderedDict([('i', 0), ('e', 2), ('o', 4)])	
	
>>> d == OrderedDict([('e', 1), ('i', 2), ('o', 3)])	
False	

collections.OrderedDict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
> 

OrderedDict  is  a  subclass  of  the  built-­‐‑in  dict  class	

> 

Remembers  the  order  that  keys  were  first  inserted	
> 

Updating  a  key  does  not  modify  its  order	

> 

Two  additional  methods:  popitem,  move_to_end	

> 

Also  supports  reverse  iteration  using  reversed	

> 

Since  Python  2.7	

collections.OrderedDict	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
And  finally,  one  last  example	

{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
class Color:	
def __init__(self, r, g, b):	
self.r = r	
self.g = g	
self.b = b	
	
class Image:	
def __init__(self, w, h, pixels):	
self.w = w	
self.h = h	
self.pixels = pixels	
	
def rotate(self):	
pass	
	
>>> pixels = [Color(127, 127, 127),	
Color(127, 100, 100),	
Color(127, 75, 75), ]	
	
>>> picture = Image(1280, 720, pixels)	

Let’s  implement  an  image	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
class Color:	
def __init__(self, r, g, b):	
self.r = r	
self.g = g	
self.b = b	
	
class Image:	
def __init__(self, w, h, pixels):	
self.w = w	
self.h = h	
self.pixels = pixels	
	
def rotate(self):	
pass	
	
>>> pixels = [Color(127, 127, 127),	
Color(127, 100, 100),	
Color(127, 75, 75), ]	
	
>>> picture = Image(1280, 720, pixels)	

Do  we  really  need  a  class?	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> from collections import namedtuple	
>>> Color = namedtuple('Color', ['r', 'g', 'b'])	
	
class Image:	
def __init__(self, w, h, pixels):	
self.w = w	
self.h = h	
self.pixels = pixels	
	
def rotate(self):	
pass	
	
>>> pixels = [Color(127, 127, 127),	
Color(127, 100, 100),	
Color(127, 75, 75), ]	
	
>>> picture = Image(1280, 720, pixels)	
	
>>> p = Color(127, 75, 25)	
>>> p[1]	
75	
>>> p.b	
25	

collections.namedtuple	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
>>> from collections import namedtuple	
>>> Color = namedtuple('Color', ['r', 'g', 'b'])	
	
class Image:	
def __init__(self, w, h, pixels):	
self.w = w	
self.h = h	
self.pixels = pixels	
	
def rotate(self):	
pass	
	
>>> pixels = [Color(127, 127, 127),	
Color(127, 100, 100),	
Color(127, 75, 75), ]	
	
>>> picture = Image(1280, 720, pixels)	
	
>>> p = Color(127, 75, 25)	
>>> p[1]	
75	
>>> p.b	
25	

collections.namedtuple	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
> 

Tuple  sublcasses  factory	
> 
> 

Indexable	

> 

Iterable	

> 

> 

A2ribute  lookup	

Helpful  docstring  and  repr	

Since  Python  2.6	

collections.namedtuple	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
Thanks  for  coming!	
	
	

Slides:	

Q&A	
{  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}

More Related Content

What's hot

Php user groupmemcached
Php user groupmemcachedPhp user groupmemcached
Php user groupmemcachedJason Anderson
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeMongoDB
 
IPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curseIPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curseYonatan Levin
 
Ipc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseIpc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseYonatan Levin
 
Server Side Events
Server Side EventsServer Side Events
Server Side Eventsthepilif
 
Using Change Streams to Keep Up with Your Data
Using Change Streams to Keep Up with Your DataUsing Change Streams to Keep Up with Your Data
Using Change Streams to Keep Up with Your DataEvan Rodd
 
Nko workshop - node js crud & deploy
Nko workshop - node js crud & deployNko workshop - node js crud & deploy
Nko workshop - node js crud & deploySimon Su
 
Mozilla とブラウザゲーム
Mozilla とブラウザゲームMozilla とブラウザゲーム
Mozilla とブラウザゲームNoritada Shimizu
 
MySQL flexible schema and JSON for Internet of Things
MySQL flexible schema and JSON for Internet of ThingsMySQL flexible schema and JSON for Internet of Things
MySQL flexible schema and JSON for Internet of ThingsAlexander Rubin
 
Intro to OTP in Elixir
Intro to OTP in ElixirIntro to OTP in Elixir
Intro to OTP in ElixirJesse Anderson
 
The Ring programming language version 1.10 book - Part 59 of 212
The Ring programming language version 1.10 book - Part 59 of 212The Ring programming language version 1.10 book - Part 59 of 212
The Ring programming language version 1.10 book - Part 59 of 212Mahmoud Samir Fayed
 
Python postgre sql a wonderful wedding
Python postgre sql   a wonderful weddingPython postgre sql   a wonderful wedding
Python postgre sql a wonderful weddingStéphane Wirtel
 
Caching and tuning fun for high scalability @ LOAD2012
Caching and tuning fun for high scalability @ LOAD2012Caching and tuning fun for high scalability @ LOAD2012
Caching and tuning fun for high scalability @ LOAD2012Wim Godden
 
All Things Open 2016 -- Database Programming for Newbies
All Things Open 2016 -- Database Programming for NewbiesAll Things Open 2016 -- Database Programming for Newbies
All Things Open 2016 -- Database Programming for NewbiesDave Stokes
 
Beyond php it's not (just) about the code
Beyond php   it's not (just) about the codeBeyond php   it's not (just) about the code
Beyond php it's not (just) about the codeWim Godden
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeWim Godden
 
Py spark cheat sheet by cheatsheetmaker.com
Py spark cheat sheet by cheatsheetmaker.comPy spark cheat sheet by cheatsheetmaker.com
Py spark cheat sheet by cheatsheetmaker.comLam Hoang
 
MongoDB全機能解説2
MongoDB全機能解説2MongoDB全機能解説2
MongoDB全機能解説2Takahiro Inoue
 

What's hot (20)

Php user groupmemcached
Php user groupmemcachedPhp user groupmemcached
Php user groupmemcached
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
 
IPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curseIPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curse
 
Ipc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseIpc: aidl sexy, not a curse
Ipc: aidl sexy, not a curse
 
Server Side Events
Server Side EventsServer Side Events
Server Side Events
 
Using Change Streams to Keep Up with Your Data
Using Change Streams to Keep Up with Your DataUsing Change Streams to Keep Up with Your Data
Using Change Streams to Keep Up with Your Data
 
Nko workshop - node js crud & deploy
Nko workshop - node js crud & deployNko workshop - node js crud & deploy
Nko workshop - node js crud & deploy
 
Mozilla とブラウザゲーム
Mozilla とブラウザゲームMozilla とブラウザゲーム
Mozilla とブラウザゲーム
 
Nantes Jug - Java 7
Nantes Jug - Java 7Nantes Jug - Java 7
Nantes Jug - Java 7
 
MySQL flexible schema and JSON for Internet of Things
MySQL flexible schema and JSON for Internet of ThingsMySQL flexible schema and JSON for Internet of Things
MySQL flexible schema and JSON for Internet of Things
 
Intro to OTP in Elixir
Intro to OTP in ElixirIntro to OTP in Elixir
Intro to OTP in Elixir
 
The Ring programming language version 1.10 book - Part 59 of 212
The Ring programming language version 1.10 book - Part 59 of 212The Ring programming language version 1.10 book - Part 59 of 212
The Ring programming language version 1.10 book - Part 59 of 212
 
Python postgre sql a wonderful wedding
Python postgre sql   a wonderful weddingPython postgre sql   a wonderful wedding
Python postgre sql a wonderful wedding
 
Caching and tuning fun for high scalability @ LOAD2012
Caching and tuning fun for high scalability @ LOAD2012Caching and tuning fun for high scalability @ LOAD2012
Caching and tuning fun for high scalability @ LOAD2012
 
All Things Open 2016 -- Database Programming for Newbies
All Things Open 2016 -- Database Programming for NewbiesAll Things Open 2016 -- Database Programming for Newbies
All Things Open 2016 -- Database Programming for Newbies
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Beyond php it's not (just) about the code
Beyond php   it's not (just) about the codeBeyond php   it's not (just) about the code
Beyond php it's not (just) about the code
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
 
Py spark cheat sheet by cheatsheetmaker.com
Py spark cheat sheet by cheatsheetmaker.comPy spark cheat sheet by cheatsheetmaker.com
Py spark cheat sheet by cheatsheetmaker.com
 
MongoDB全機能解説2
MongoDB全機能解説2MongoDB全機能解説2
MongoDB全機能解説2
 

Viewers also liked

An Introduction to Object-Oriented Programming (DrupalCamp North 2015)
An Introduction to Object-Oriented Programming (DrupalCamp North 2015)An Introduction to Object-Oriented Programming (DrupalCamp North 2015)
An Introduction to Object-Oriented Programming (DrupalCamp North 2015)Bart Feenstra
 
EuroPython 2015 - Decorators demystified
EuroPython 2015 - Decorators demystifiedEuroPython 2015 - Decorators demystified
EuroPython 2015 - Decorators demystifiedPablo Enfedaque
 
Oop concepts classes_objects
Oop concepts classes_objectsOop concepts classes_objects
Oop concepts classes_objectsWilliam Olivier
 
Message-passing concurrency in Python
Message-passing concurrency in PythonMessage-passing concurrency in Python
Message-passing concurrency in PythonSarah Mount
 
Meta-Classes in Python
Meta-Classes in PythonMeta-Classes in Python
Meta-Classes in PythonGuy Wiener
 
Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.
Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.
Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.Samuel Fortier-Galarneau
 
Python decorators
Python decoratorsPython decorators
Python decoratorsAlex Su
 
Multiprocessing with python
Multiprocessing with pythonMultiprocessing with python
Multiprocessing with pythonPatrick Vergain
 
Prepping the Analytics organization for Artificial Intelligence evolution
Prepping the Analytics organization for Artificial Intelligence evolutionPrepping the Analytics organization for Artificial Intelligence evolution
Prepping the Analytics organization for Artificial Intelligence evolutionRamkumar Ravichandran
 
QCon Rio - Machine Learning for Everyone
QCon Rio - Machine Learning for EveryoneQCon Rio - Machine Learning for Everyone
QCon Rio - Machine Learning for EveryoneDhiana Deva
 
Python for Image Understanding: Deep Learning with Convolutional Neural Nets
Python for Image Understanding: Deep Learning with Convolutional Neural NetsPython for Image Understanding: Deep Learning with Convolutional Neural Nets
Python for Image Understanding: Deep Learning with Convolutional Neural NetsRoelof Pieters
 
Tutorial on Deep learning and Applications
Tutorial on Deep learning and ApplicationsTutorial on Deep learning and Applications
Tutorial on Deep learning and ApplicationsNhatHai Phan
 
An Introduction to Supervised Machine Learning and Pattern Classification: Th...
An Introduction to Supervised Machine Learning and Pattern Classification: Th...An Introduction to Supervised Machine Learning and Pattern Classification: Th...
An Introduction to Supervised Machine Learning and Pattern Classification: Th...Sebastian Raschka
 
Hands-on Deep Learning in Python
Hands-on Deep Learning in PythonHands-on Deep Learning in Python
Hands-on Deep Learning in PythonImry Kissos
 
Deep Learning - The Past, Present and Future of Artificial Intelligence
Deep Learning - The Past, Present and Future of Artificial IntelligenceDeep Learning - The Past, Present and Future of Artificial Intelligence
Deep Learning - The Past, Present and Future of Artificial IntelligenceLukas Masuch
 

Viewers also liked (20)

An Introduction to Object-Oriented Programming (DrupalCamp North 2015)
An Introduction to Object-Oriented Programming (DrupalCamp North 2015)An Introduction to Object-Oriented Programming (DrupalCamp North 2015)
An Introduction to Object-Oriented Programming (DrupalCamp North 2015)
 
EuroPython 2015 - Decorators demystified
EuroPython 2015 - Decorators demystifiedEuroPython 2015 - Decorators demystified
EuroPython 2015 - Decorators demystified
 
Oop concepts classes_objects
Oop concepts classes_objectsOop concepts classes_objects
Oop concepts classes_objects
 
Message-passing concurrency in Python
Message-passing concurrency in PythonMessage-passing concurrency in Python
Message-passing concurrency in Python
 
Meta-Classes in Python
Meta-Classes in PythonMeta-Classes in Python
Meta-Classes in Python
 
Python decorators
Python decoratorsPython decorators
Python decorators
 
Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.
Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.
Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.
 
Python decorators
Python decoratorsPython decorators
Python decorators
 
Multiprocessing with python
Multiprocessing with pythonMultiprocessing with python
Multiprocessing with python
 
Interfacing C/C++ and Python with SWIG
Interfacing C/C++ and Python with SWIGInterfacing C/C++ and Python with SWIG
Interfacing C/C++ and Python with SWIG
 
Python in Action (Part 1)
Python in Action (Part 1)Python in Action (Part 1)
Python in Action (Part 1)
 
Prepping the Analytics organization for Artificial Intelligence evolution
Prepping the Analytics organization for Artificial Intelligence evolutionPrepping the Analytics organization for Artificial Intelligence evolution
Prepping the Analytics organization for Artificial Intelligence evolution
 
Mastering Python 3 I/O (Version 2)
Mastering Python 3 I/O (Version 2)Mastering Python 3 I/O (Version 2)
Mastering Python 3 I/O (Version 2)
 
An Introduction to Python Concurrency
An Introduction to Python ConcurrencyAn Introduction to Python Concurrency
An Introduction to Python Concurrency
 
QCon Rio - Machine Learning for Everyone
QCon Rio - Machine Learning for EveryoneQCon Rio - Machine Learning for Everyone
QCon Rio - Machine Learning for Everyone
 
Python for Image Understanding: Deep Learning with Convolutional Neural Nets
Python for Image Understanding: Deep Learning with Convolutional Neural NetsPython for Image Understanding: Deep Learning with Convolutional Neural Nets
Python for Image Understanding: Deep Learning with Convolutional Neural Nets
 
Tutorial on Deep learning and Applications
Tutorial on Deep learning and ApplicationsTutorial on Deep learning and Applications
Tutorial on Deep learning and Applications
 
An Introduction to Supervised Machine Learning and Pattern Classification: Th...
An Introduction to Supervised Machine Learning and Pattern Classification: Th...An Introduction to Supervised Machine Learning and Pattern Classification: Th...
An Introduction to Supervised Machine Learning and Pattern Classification: Th...
 
Hands-on Deep Learning in Python
Hands-on Deep Learning in PythonHands-on Deep Learning in Python
Hands-on Deep Learning in Python
 
Deep Learning - The Past, Present and Future of Artificial Intelligence
Deep Learning - The Past, Present and Future of Artificial IntelligenceDeep Learning - The Past, Present and Future of Artificial Intelligence
Deep Learning - The Past, Present and Future of Artificial Intelligence
 

Similar to The (unknown) collections module

Kotlin: forse è la volta buona (Trento)
Kotlin: forse è la volta buona (Trento)Kotlin: forse è la volta buona (Trento)
Kotlin: forse è la volta buona (Trento)Davide Cerbo
 
jq: JSON - Like a Boss
jq: JSON - Like a Bossjq: JSON - Like a Boss
jq: JSON - Like a BossBob Tiernay
 
PostgreSQL Open SV 2018
PostgreSQL Open SV 2018PostgreSQL Open SV 2018
PostgreSQL Open SV 2018artgillespie
 
Erlang for data ops
Erlang for data opsErlang for data ops
Erlang for data opsmnacos
 
Kotlin: maybe it's the right time
Kotlin: maybe it's the right timeKotlin: maybe it's the right time
Kotlin: maybe it's the right timeDavide Cerbo
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsMichael Pirnat
 
第二讲 Python基礎
第二讲 Python基礎第二讲 Python基礎
第二讲 Python基礎juzihua1102
 
第二讲 预备-Python基礎
第二讲 预备-Python基礎第二讲 预备-Python基礎
第二讲 预备-Python基礎anzhong70
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Snakes for Camels
Snakes for CamelsSnakes for Camels
Snakes for Camelsmiquelruizm
 
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Eelco Visser
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Codemotion
 
GE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python ProgrammingGE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python ProgrammingMuthu Vinayagam
 
Building Apps with MongoDB
Building Apps with MongoDBBuilding Apps with MongoDB
Building Apps with MongoDBNate Abele
 
Herding types with Scala macros
Herding types with Scala macrosHerding types with Scala macros
Herding types with Scala macrosMarina Sigaeva
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to PythonUC San Diego
 

Similar to The (unknown) collections module (20)

Decorators demystified
Decorators demystifiedDecorators demystified
Decorators demystified
 
Kotlin: forse è la volta buona (Trento)
Kotlin: forse è la volta buona (Trento)Kotlin: forse è la volta buona (Trento)
Kotlin: forse è la volta buona (Trento)
 
jq: JSON - Like a Boss
jq: JSON - Like a Bossjq: JSON - Like a Boss
jq: JSON - Like a Boss
 
PostgreSQL Open SV 2018
PostgreSQL Open SV 2018PostgreSQL Open SV 2018
PostgreSQL Open SV 2018
 
Erlang for data ops
Erlang for data opsErlang for data ops
Erlang for data ops
 
Kotlin: maybe it's the right time
Kotlin: maybe it's the right timeKotlin: maybe it's the right time
Kotlin: maybe it's the right time
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 
第二讲 Python基礎
第二讲 Python基礎第二讲 Python基礎
第二讲 Python基礎
 
第二讲 预备-Python基礎
第二讲 预备-Python基礎第二讲 预备-Python基礎
第二讲 预备-Python基礎
 
MongoDB
MongoDBMongoDB
MongoDB
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Snakes for Camels
Snakes for CamelsSnakes for Camels
Snakes for Camels
 
Rust
RustRust
Rust
 
Procesamiento del lenguaje natural con python
Procesamiento del lenguaje natural con pythonProcesamiento del lenguaje natural con python
Procesamiento del lenguaje natural con python
 
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
 
GE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python ProgrammingGE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python Programming
 
Building Apps with MongoDB
Building Apps with MongoDBBuilding Apps with MongoDB
Building Apps with MongoDB
 
Herding types with Scala macros
Herding types with Scala macrosHerding types with Scala macros
Herding types with Scala macros
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
 

More from Pablo Enfedaque

Execution model and other must-know's
Execution model and other must-know'sExecution model and other must-know's
Execution model and other must-know'sPablo Enfedaque
 
Sprayer: low latency, reliable multichannel messaging
Sprayer: low latency, reliable multichannel messagingSprayer: low latency, reliable multichannel messaging
Sprayer: low latency, reliable multichannel messagingPablo Enfedaque
 
Python: the coolest is yet to come
Python: the coolest is yet to comePython: the coolest is yet to come
Python: the coolest is yet to comePablo Enfedaque
 

More from Pablo Enfedaque (6)

Why I miss MongoDB
Why I miss MongoDBWhy I miss MongoDB
Why I miss MongoDB
 
Python 2 vs. Python 3
Python 2 vs. Python 3Python 2 vs. Python 3
Python 2 vs. Python 3
 
Execution model and other must-know's
Execution model and other must-know'sExecution model and other must-know's
Execution model and other must-know's
 
Sprayer: low latency, reliable multichannel messaging
Sprayer: low latency, reliable multichannel messagingSprayer: low latency, reliable multichannel messaging
Sprayer: low latency, reliable multichannel messaging
 
Python: the coolest is yet to come
Python: the coolest is yet to comePython: the coolest is yet to come
Python: the coolest is yet to come
 
From Oracle to MongoDB
From Oracle to MongoDBFrom Oracle to MongoDB
From Oracle to MongoDB
 

Recently uploaded

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 

The (unknown) collections module

  • 1. The  unknown   COLLECTIONS module { “event”:      “PyCon  ES  2013” “author”:  “Pablo  Enfedaque” “twi2er”:  “pablitoev56”
  • 2. Today  we  are  going  to  talk  about  the   (unknown)  collections  module And  also  about  built-­‐‑in  containers Welcome! {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 3. “This  module  implements   specialized  container  datatypes   providing  alternatives  to  Python’s   general  purpose  built-­‐‑in  containers,   dict,  list,  set,  and  tuple” The  collections  module {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 4. Let’s  start  with  Python’s  most  used   container {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 5. Yes,  that’s  dict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 6. >>> d = {'a': 1, 'b': 2, 'c': 3} >>> d['b'] 2 >>> d['d'] = 4 >>> d {'d': 4, 'b': 2, 'c': 3, 'a': 1} >>> d['e'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'e' >>> print(d.get('e')) None >>> d.get('e', 5) 5 dict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 7. OPERATION AVERAGE AMORTIZED  WORST Get  item    d['b'] O(1) O(n) Set  item      d['d'] = 4 O(1)* O(n) Delete  item    del d['b'] O(1) O(n) Copy    new_d = dict(d) O(n) O(N) Iteration    for k in d: O(n) O(N) >  Internally  implemented  with  an  optimised  hash  map >  *:  Amortized  cost.  Individual  ops  may  be  really  slow >  N:  Maximum  size  the  container  ever  achieved dict  performance {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 8. And  what  about  set? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 9. >>> vowels = {'a', 'e', 'i', 'o', 'u'} >>> letters = set(['a', 'b', 'c', 'd', 'e']) >>> vowels – letters {'i', 'o', 'u’} >>> vowels & letters {'a', 'e’} >>> vowels | letters {'u', 'i', 'o', 'c', 'b', 'a', 'e', 'd’} >>> vowels ^ letters {'u', 'i', 'o', 'c', 'b', 'd'} >>> 'b' in letters True >>> letters.add('a') >>> letters {'c', 'b', 'a', 'e', 'd'} >>> letters.update(['d', 'e', 'f', 'g']) >>> letters {'c', 'b', 'a', 'g', 'f', 'e', 'd'} set {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 10. OPERATION AVERAGE AMORTIZED  WORST Check  item        'b' in s1 O(1) O(n) Union                                  s1 | s2 O(len(s1)  +  len(s2)) Intersection              s1 & s2 O(min(len(s1),  len(s2))) Difference                    s1 – s2 O(len(s1)) Symmetric  diff    s1 ^ s2   O(len(s1)) O(len(s1)  *  len(s2)) >  >  O(len(s1)  *  len(s2)) Implementation  very  similar  to  dicts  (hash  map) Also  has  in-­‐‑place  modification  methods  (its  average   cost  depends  on  s2) set  performance {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 11. A  bit  boring,  isn’t  it? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 12. Let'ʹs  do  something  more  appealing {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 13. txt = """El desconocido módulo Collections Todo el mundo conoce los tipos básicos de Python y sus contenedores más comunes (list, tuple, dict y set). En cambio, poca gente sabe que para implementar una cola debería utilizar un deque, que con un defaultdict su código quedaría más limpio y sería un poco más eficiente o que podría utilizar namedtuples en lugar de crear nuevas clases. En esta charla repasaremos las estructuras del módulo collections de la librería estándar: namedtuple, deque, Counter, OrderedDict y defaultdict. Veremos su funcionalidad, particularidades y casos prácticos de uso. Pablo Enfedaque Vidal Trabajo como R&D SW Engineer en Telefónica PDI en Barcelona, y desde hace más de 5 años casi exclusivamente con Python, un lenguaje que me encanta""" During  the  talk  we  will  use  this  str {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 14. >>> initials = {} def classify_words(text): for word in text.split(): word = word.lower() if word[0] in initials: initials[word[0]].append(word) else: initials[word[0]] = [word, ] for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y ['y', 'y', 'y', 'y', 'y', 'y'] s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw'] r ['repasaremos', 'r&d'] q ['que', 'que', 'quedaría', 'que', 'que'] ... Let’s  classify  words {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 15. >>> initials = {} def classify_words(text): for word in text.split(): word = word.lower() if word[0] in initials: initials[word[0]].append(word) else: initials[word[0]] = [word, ] for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y ['y', 'y', 'y', 'y', 'y', 'y'] s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw'] r ['repasaremos', 'r&d'] q ['que', 'que', 'quedaría', 'que', 'que'] ... Does  it  look  pythonic? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 16. >>> initials = {} def classify_words(text): for word in text.split(): word = word.lower() initials.setdefault(word[0], []).append(word) for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y ['y', 'y', 'y', 'y', 'y', 'y'] s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw'] r ['repasaremos', 'r&d'] q ['que', 'que', 'quedaría', 'que', 'que'] ... What  about  now? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 17. from collections import defaultdict >>> initials = defaultdict(list) def classify_words(text): for word in text.split(): word = word.lower() initials[word[0]].append(word) for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y ['y', 'y', 'y', 'y', 'y', 'y'] s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw'] r ['repasaremos', 'r&d'] q ['que', 'que', 'quedaría', 'que', 'que'] ... collections.defaultdict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 18. from collections import defaultdict >>> initials = defaultdict(list) def classify_words(text): for word in text.split(): word = word.lower() initials[word[0]].append(word) for letter, letter_words in initials.items(): print(letter, letter_words) >>> initials.default_factory <class 'list'> >>> classify_words(txt) y ['y', 'y', 'y', 'y', 'y', 'y'] s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw'] r ['repasaremos', 'r&d'] q ['que', 'que', 'quedaría', 'que', 'que'] ... collections.defaultdict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 19. >  defaultdict  is  a  subclass  of  the  built-­‐‑in  dict  class >  The  first  argument  provides  the  initial  value  for  the   default_factory  a2ribute  (it  defaults  to  None) >  All  remaining  arguments  are  treated  the  same >  It  also  overrides  the  __missing__  method  to  call  the   default_factory  when  an  key  is  not  found >  default_factory  may  raise  an  exception  (e.g.  KeyError) >  Since  Python  2.5 collections.defaultdict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 20. Let’s  continue  classifying  words {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 21. class WordsByInitial(): "Holds initial letter and a set and a list of words" def __init__(self, letter): self.letter = letter self.words = [] self.unique_words = set() def append(self, word): self.words.append(word) self.unique_words.add(word) def __str__(self): return "<{}: {} {}>".format(self.letter, self.unique_words, self.words) >>> a_words = WordsByInitial('a') >>> a_words.append('ahora') >>> a_words.append('adios') >>> a_words.append('ahora') >>> print(a_words) <a: {'adios', 'ahora'} ['ahora', 'adios', 'ahora']> Now  we  have  this  custom  class {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 22. What  if  we  want  to  use  our  class  with   defaultdict? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 23. class WordsByInitial(): "Holds initial letter and set and list of words" def __init__(self, letter): self.letter = letter self.words = [] self.unique_words = set() def append(self, word): self.words.append(word) self.unique_words.add(word) def __str__(self): return "<{}: {} {}>".format(self.letter, self.unique_words, self.words) >>> a_words = WordsByInitial('a') >>> a_words.append('ahora') >>> a_words.append('adios') >>> a_words.append('ahora') >>> print(a_words) <a: {'adios', 'ahora'} ['ahora', 'adios', 'ahora']> How  do  we  get  the  le2er? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 24. What  if  we  want  the  default_factory   to  receive  the  missing  key? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 25. class WordsDict(dict): def __missing__(self, key): res = self[key] = WordsByInitial(key) return res initials = WordsDict() def classify_words(text): for word in text.split(): word = word.lower() initials[word[0]].append(word) for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y <y: {'y'} ['y', 'y', 'y', 'y', 'y', 'y']> s <s: {'sería', 'sus', 'set).', 'sabe', 'sw', 'su'} ['sus’... r <r: {'r&d', 'repasaremos'} ['repasaremos', 'r&d']> q <q: {'quedaría', 'que'} ['que', 'que', 'quedaría', 'que’... ... Time  to  code  our  custom  dict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 26. class WordsDict(dict): def __missing__(self, key): res = self[key] = WordsByInitial(key) return res initials = WordsDict() def classify_words(text): for word in text.split(): word = word.lower() initials[word[0]].append(word) for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y <y: {'y'} ['y', 'y', 'y', 'y', 'y', 'y']> s <s: {'sería', 'sus', 'set).', 'sabe', 'sw', 'su'} ['sus’... r <r: {'r&d', 'repasaremos'} ['repasaremos', 'r&d']> q <q: {'quedaría', 'que'} ['que', 'que', 'quedaría', 'que’... ... Subclass  overriding  __missing__ {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 27. Let'ʹs  move  on  to  something  different {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 28. from collections import defaultdict def wordcount(s): wc = defaultdict(int) for word in s.split(): wc[word] += 1 return wc >>> wc = wordcount(txt) >>> for letter, num in wc.items(): print(letter, num) del 1 implementar 1 exclusivamente 1 más 4 y 6 ... >>> sorted(wc.items(), reverse=True, key=lambda x: x[1])[:3] [('y', 6), ('de', 5), ('más', 4)] Let’s  count  words {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 29. from collections import Counter def wordcount(s): return Counter(s.split()) >>> wc = wordcount(txt) >>> for letter, num in wc.items(): print(letter, num) del 1 implementar 1 exclusivamente 1 más 4 y 6 ... >>> wc.most_common(3) [('y', 6), ('de', 5), ('más', 4)] collections.Counter {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 30. from collections import Counter def wordcount(s): return Counter(s.split()) >>> wc = wordcount(txt) >>> for letter, num in wc.items(): print(letter, num) del 1 implementar 1 exclusivamente 1 más 4 y 6 ... >>> wc.most_common(3) [('y', 6), ('de', 5), ('más', 4)] collections.Counter {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 31. >>> c1 = Counter(a=3, e=2, i=-1, o=5) >>> c2 = Counter(a=1, b=1, c=1, d=1, e=1) >>> c1['u'] 0 >>> c1.most_common(2) [('o', 5), ('a', 3)] >>> list(c1.elements()) ['o', 'o', 'o', 'o', 'o', 'a', 'a', 'a', 'e', 'e'] >>> c1.subtract(c2) >>> c1 Counter({'o': 5, 'a': 2, 'e': 1, 'c': -1, 'b': -1, 'd': -1, 'i': -1}) >>> c1.update(['b', 'c', 'd']) >>> c1 Counter({'o': 5, 'a': 2, 'e': 1, 'c': 0, 'b': 0, 'd': 0, 'i': -1}) More  on  collections.Counter {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 32. >>> c1 = Counter(a=3, >>> c2 = Counter(a=1, >>> c1 + c2 Counter({'o': 5, 'a': >>> c1 - c2 Counter({'o': 5, 'a': >>> c1 & c2 Counter({'a': 1, 'e': >>> c1 | c2 Counter({'o': 5, 'a': >>> +c1 Counter({'o': 5, 'a': >>> -c1 Counter({'i': 1}) e=2, i=-1, o=5) b=1, c=1, d=1, e=1) 3, 'e': 2, 'c': 1, 'b': 1, 'd': 1}) 1}) 1}) 2, 'c': 1, 'b': 1, 'e': 1, 'd': 1}) 2, 'e': 1}) More  on  collections.Counter {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 33. >  Counter  is  a  dict  subclass  for  counting  hashable  objects >  dict  interface  but  they  return  0  instead  of  KeyError >  Three  additional  methods:  most_common,  elements,   subtract >  update  method  has  been  overriden >  Support  for  mathematical  operators:  +,  -­‐‑,  &,  | >  Since  Python  2.7 collections.Counter {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 34. Let'ʹs  go  back  to  words  classification {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 35. from collections import defaultdict >>> initials = defaultdict(list) def classify_words(text): for word in text.split(): word = word.lower() initials[word[0]].append(word) for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y ['y', 'y', 'y', 'y', 'y', 'y'] s ['sus', 'set).', 'sabe', 'su', 'sería', 'su', 'sw'] r ['repasaremos', 'r&d'] q ['que', 'que', 'quedaría', 'que', 'que'] ... Classify  words  with  defaultdict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 36. What  if  we  only  want  to  keep  the last  three  words  for  each  le2er? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 37. from collections import defaultdict, deque >>> initials = defaultdict(lambda: deque(maxlen=3)) def classify_words(text): for word in text.split(): word = word.lower() initials[word[0]].append(word) for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y deque(['y', 'y', 'y'], maxlen=3) s deque(['sería', 'su', 'sw'], maxlen=3) r deque(['repasaremos', 'r&d'], maxlen=3) q deque(['quedaría', 'que', 'que'], maxlen=3) ... collections.deque {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 38. from collections import defaultdict, deque >>> initials = defaultdict(lambda: deque(maxlen=3)) def classify_words(text): for word in text.split(): word = word.lower() initials[word[0]].append(word) for letter, letter_words in initials.items(): print(letter, letter_words) >>> classify_words(txt) y deque(['y', 'y', 'y'], maxlen=3) s deque(['sería', 'su', 'sw'], maxlen=3) r deque(['repasaremos', 'r&d'], maxlen=3) q deque(['quedaría', 'que', 'que'], maxlen=3) ... collections.deque {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 39. >>> d = deque(maxlen=5) >>> d.extend(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']) >>> d deque(['d', 'e', 'f', 'g', 'h'], maxlen=5) >>> d.append('i') >>> d deque(['e', 'f', 'g', 'h', 'i'], maxlen=5) >>> d.appendleft('Z') >>> d deque(['Z', 'e', 'f', 'g', 'h'], maxlen=5) >>> d.rotate(3) >>> d deque(['f', 'g', 'h', 'Z', 'e'], maxlen=5) >>> d.popleft() 'f’ >>> d deque(['g', 'h', 'Z', 'e'], maxlen=5) More  on  collections.deque {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 40. OPERATION AVERAGE AMORTIZED  WORST append('b’) O(1) O(1) appendleft('b’) O(1) O(1) pop() O(1) O(1) popleft() O(1) O(1) extend(iterable) O(k) O(k) extendleft(iterable) O(k) O(k) rotate() O(k) O(k) remove('b’) O(n) O(n) >  Represented  internally  as  a  doubly  linked  list >  Ideal  to  implement  queues  (FIFO) >  Since  Python  2.4   deque  performance {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 41. OPERATION AVERAGE AMORTIZED  WORST append('b’) O(1)* O(1)* insert(index, 'b’) O(n) O(n) Get  item    d[4] O(1) O(1) Set  item      d[4] = 'd' O(1) O(1) Delete  item    del d[4] O(n) O(n) extend(iterable) O(k)* O(k)* Check  item    'b' in list O(n) O(n) O(n  log  n) O(n  log  n) Sort >  Represented  internally  as  an  array >  *:  Amortized  cost.  Individual  ops  may  be  really  slow >  Ideal  to  implement  stacks  (LIFO) list  performance {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 42. Let’s  move  to  a  different  example {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 43. CACHE = {} def set_key(key, value): "Set a key value" CACHE[key] = value def get_key(key): "Retrieve a key value from the cache, or None if not found" return CACHE.get(key, None) >>> set_key("my_key", "the_value”) >>> print(get_key("my_key")) the_value >>> print(get_key("not_found_key")) None Let’s  implement  a  SW  cache {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 44. What  if  we  want  to  limit  its  size? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 45. from collections import OrderedDict CACHE = OrderedDict() MAX_SIZE = 3 def set_key(key, value): "Set a key value, removing oldest key if MAX_SIZE exceeded" CACHE[key] = value if len(CACHE) > MAX_SIZE: CACHE.popitem(last=False) def get_key(key): "Retrieve a key value from the cache, or None if not found" return CACHE.get(key, None) >>> set_key("my_key", "the_value”) >>> print(get_key("my_key")) the_value >>> print(get_key("not_found_key")) None >>> CACHE OrderedDict([('c', 3), ('d', 4), ('e', 5)]) collections.OrderedDict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 46. from collections import OrderedDict CACHE = OrderedDict() MAX_SIZE = 3 def set_key(key, value): "Set a key value, removing oldest key if MAX_SIZE exceeded" CACHE[key] = value if len(CACHE) > MAX_SIZE: CACHE.popitem(last=False) def get_key(key): "Retrieve a key value from the cache, or None if not found" return CACHE.get(key, None) >>> set_key("my_key", "the_value”) >>> print(get_key("my_key")) the_value >>> print(get_key("not_found_key")) None >>> CACHE OrderedDict([('c', 3), ('d', 4), ('e', 5)]) collections.OrderedDict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 47. >>> d = OrderedDict() >>> d.update([(‘a', 1), (‘e', 2), ('i', 3), ('o', 4), ('u', 5)]) >>> d OrderedDict([('a', 1), ('e', 2), ('i', 3), ('o', 4), ('u', 5)]) >>> d['i'] = 0 >>> list(d.items()) [('a', 1), ('e', 2), ('i', 0), ('o', 4), ('u', 5)] >>> d.popitem() ('u', 5) >>> d.popitem(last=False) ('a', 1) >>> d OrderedDict([('e', 2), ('i', 0), ('o', 4)]) >>> d.move_to_end('i') >>> d OrderedDict([('e', 2), ('o', 4), ('i', 0)]) >>> d.move_to_end('i', last=False) >>> d OrderedDict([('i', 0), ('e', 2), ('o', 4)]) >>> d == OrderedDict([('e', 1), ('i', 2), ('o', 3)]) False collections.OrderedDict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 48. >  OrderedDict  is  a  subclass  of  the  built-­‐‑in  dict  class >  Remembers  the  order  that  keys  were  first  inserted >  Updating  a  key  does  not  modify  its  order >  Two  additional  methods:  popitem,  move_to_end >  Also  supports  reverse  iteration  using  reversed >  Since  Python  2.7 collections.OrderedDict {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 49. And  finally,  one  last  example {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 50. class Color: def __init__(self, r, g, b): self.r = r self.g = g self.b = b class Image: def __init__(self, w, h, pixels): self.w = w self.h = h self.pixels = pixels def rotate(self): pass >>> pixels = [Color(127, 127, 127), Color(127, 100, 100), Color(127, 75, 75), ] >>> picture = Image(1280, 720, pixels) Let’s  implement  an  image {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 51. class Color: def __init__(self, r, g, b): self.r = r self.g = g self.b = b class Image: def __init__(self, w, h, pixels): self.w = w self.h = h self.pixels = pixels def rotate(self): pass >>> pixels = [Color(127, 127, 127), Color(127, 100, 100), Color(127, 75, 75), ] >>> picture = Image(1280, 720, pixels) Do  we  really  need  a  class? {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 52. >>> from collections import namedtuple >>> Color = namedtuple('Color', ['r', 'g', 'b']) class Image: def __init__(self, w, h, pixels): self.w = w self.h = h self.pixels = pixels def rotate(self): pass >>> pixels = [Color(127, 127, 127), Color(127, 100, 100), Color(127, 75, 75), ] >>> picture = Image(1280, 720, pixels) >>> p = Color(127, 75, 25) >>> p[1] 75 >>> p.b 25 collections.namedtuple {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 53. >>> from collections import namedtuple >>> Color = namedtuple('Color', ['r', 'g', 'b']) class Image: def __init__(self, w, h, pixels): self.w = w self.h = h self.pixels = pixels def rotate(self): pass >>> pixels = [Color(127, 127, 127), Color(127, 100, 100), Color(127, 75, 75), ] >>> picture = Image(1280, 720, pixels) >>> p = Color(127, 75, 25) >>> p[1] 75 >>> p.b 25 collections.namedtuple {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 54. >  Tuple  sublcasses  factory >  >  Indexable >  Iterable >  >  A2ribute  lookup Helpful  docstring  and  repr Since  Python  2.6 collections.namedtuple {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}
  • 55. Thanks  for  coming! Slides: Q&A {  “event”:  “PyCon  ES  2013”,  “author”:  “Pablo  Enfedaque”,  “twi2er”:  “pablitoev56”}