Py24L12fin (1)
Py24L12fin (1)
Le Slid
ctu e
re 33
Lesson #4: The filter may save computation:
10
>>> from x import prime
>>> [2*x+1 for x in range(15) if prime (2*x+1)]
[3, 5, 7, 11, 13, 17, 19, 23, 29]
>>> list(filter(prime,[2*x+1 for x in range(15)]))
[3, 5, 7, 11, 13, 17, 19, 23, 29]
Later we’ll learn about the
Notice that the comprehension required
“assignment the
expression.”
“2*x+1” to be typed twice. That allows this computation
to only be performed
This also means that it is calculated twice. once.
If “2*x+1” were replaced with something more
complex (eg: sqrt(sqrt(sqrt(x)))), then the cost of
calculating twice could be significant for long lists.
Expression Assignments
>>> from random import randrange as Rn
>>> Ns=range(10) What this output means is that 6
of the randomiterations
>>> [x for x in Ns if Rn(9)<5]#Which numbers were <
match?
[0, 2, 6] 5.
For each of those,
>>> [x for x in Ns if Rn(9)<5]#Which a new random
iterations match?
[1, 2, 3, 5, 7] number was generated. Some of
those new
>>> #But how to get those values? numbers
This won'tare 5.
work:
>>> [R(9) for x in Ns if Rn(9)<5]#This gives #s >= 5
[7, 2, 7, 0, 8, 5]
>>> #The problem is the expression value became lost.
>>> #Use an "expression assignment" to keep it:
>>> [y for x in Ns if (y:=Rn(9))<5]
[0, 1, 3, 1]
>>> [y for x in Ns if (y:=Rn(9)<5)]#Saves the < exprsn
[True, True, True]
>>> [y for x in Ns if y:=Rn(9)<5] # We needed the ( )
Expression Assignments
>>> from random import randrange as Rn
>>> Ns=range(10)
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[0, 2, 6]
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[1, 2, 3, 5, 7]
>>> #But how to get those values? This won't work:
>>> [R(9) for x in Ns if Rn(9)<5]#This gives #s >= 5
[7, 2, 7, 0, 8, 5]
>>> #The problem is the expression value became lost.
>>> #Use an "expression assignment" to keep it:
>>> [y for x in Ns if (y:=Rn(9))<5]
[0, 1, 3, 1]
>>> [y for x in Ns if (y:=Rn(9)<5)]#Saves the < exprsn
[True, True, True]
>>> [y for x in Ns if y:=Rn(9)<5] # We needed the ( )
File "<stdin>", line 1
Expression Assignments
>>> from random import randrange as Rn
>>> Ns=range(10)
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[0, 2, 6]
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[1, 2, 3, 5, 7]
>>> #But how to get those values? This won't work:
>>> [R(9) for x in Ns if Rn(9)<5]#This gives #s >= 5
[7, 2, 7, 0, 8, 5]
>>> #The problem is the expression value became lost.
>>> #Use an "expression assignment" to keep it:
>>> [y for x in Ns if (y:=Rn(9))<5]
[0, 1, 3, 1]
>>> [y for x in Ns if (y:=Rn(9)<5)]#Saves the < exprsn
[True, True, True]
>>> [y for x in Ns if y:=Rn(9)<5] # We needed the ( )
File "<stdin>", line 1
[y for x in Ns if y:=Rn(9)<5] # We needed the ( )
Expression Assignments
>>> from random import randrange as Rn
>>> Ns=range(10)
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[0, 2, 6]
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[1, 2, 3, 5, 7]
>>> #But how to get those values? This won't work:
>>> [R(9) for x in Ns if Rn(9)<5]#This gives #s >= 5
[7, 2, 7, 0, 8, 5]
>>> #The problem is the expression value became lost.
>>> #Use an "expression assignment" to keep it:
>>> [y for x in Ns if (y:=Rn(9))<5]
[0, 1, 3, 1]
>>> [y for x in Ns if (y:=Rn(9)<5)]#Saves the < exprsn
[True, True, True]
>>> [y for x in Ns if y:=Rn(9)<5] # We needed the ( )
File "<stdin>", line 1
[y for x in Ns if y:=Rn(9)<5] # We needed the ( )
Expression Assignments
>>> Ns=range(10)
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[0, 2, 6]
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[1, 2, 3, 5, 7]
>>> #But how to get those values? This won't work:
>>> [R(9) for x in Ns if Rn(9)<5]#This gives #s >= 5
[6, 2, 6, 0, 8, 5]
>>> #The problem is the expression value became lost.
>>> #Use an "expression assignment" to keep it:
>>> [y for x in Ns if (y:=Rn(9))<5]
[0, 1, 3, 1]
>>> [y for x in Ns if (y:=Rn(9)<5)]#Saves the < exprsn
[True, True, True]
>>> [y for x in Ns if y:=Rn(9)<5] # We needed the ( )
File "<stdin>", line 1
[y for x in Ns if y:=Rn(9)<5] # We needed the ( )
^
SyntaxError: invalid syntax
Expression Assignments
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[0, 2, 6] Works with no ( )
>>> [x for x in Ns if Rn(9)<5]#Which iterations match?
[1, 2, 3, 5, 7]
>>> #But how to get those values? This won't work:
>>> [R(9) for x in Ns if Rn(9)<5]#This gives #s >= 5
[7, 2, 7, 0, 8, 5]
Works with ( )
>>> #The problem is the expression value became lost.
>>> #Use an "expression assignment" to keep it:
>>> [y for x in Ns if (y:=Rn(9))<5]
[0, 1, 3, 1] Fails with no ( )
>>> [y for x in Ns if (y:=Rn(9)<5)]#Saves the < exprsn
[True, True, True]
>>> [y for x in Ns if y:=Rn(9)<5] # We needed the ( )
File "<stdin>", line 1
[y for x in Ns if y:=Rn(9)<5] # We needed the ( )
^
SyntaxError: invalid syntax
>>>
Let's def ine a timer function
>>> from time import time, sleep
>>> def timer(com="START",was=[0]):
... ..if com=="START": was[0]=time()
... ..else: print(' ',
... .. . f'{int(1000000*(time()-was[0])):,d}','usec')
...
>>> timer(); sleep(2); timer("STOP")
2,000,056 usec
>>> def f(x): sleep(1); return x
...
>>> timer(); f(None); timer("STOP")
1,000,107 usec
>>> timer(); f(None); timer("STOP")
1,000,212 usec
>>> import os;os.system("cat timer.py")#Can download
this
from time import time
def timer(com="START",was=[0]):
if com=="START": was[0]=time()
else: print(' ',
Expression Assignments
Can Save Time:
>>> from timer import timer; from time import sleep
>>> timer(); sleep(2); timer("STOP")
2,000,058 usec
>>> def f(x): sleep(1); return x
...
>>> timer(); f(None); timer("STOP")
1,000,126 usec
>>> from prime import prime #You can download this
>>> timer();[2*f(x)+1 for x in range(15)
... if prime(2*f(x)+1)]; timer("STOP")
[3, 5, 7, 11, 13, 17, 19, 23, 29]
24,036,369 usec
>>> timer();[y for x in range(15)
... if prime(y:=2*f(x)+1)]; timer("STOP")
[1, 3, 5, 7, 11, 13, 17, 19, 23, 29]
15,030,192 usec
>>> # It was 9 sec faster without the recompute
Functional Programming
• Python allows functional programming style.
• But that is not to say that everyone should
use a functional programming style.
• Most Python programming is not functional.
• Yet it has some advantages (fewer bugs,
occasionally clearer code), so it can be
used sometimes, even in programs that
are predominantly procedural.
• Three Python functions are key:
• map( ), filter( ), functools.reduce()
Different types of programming languages:
Procedural languages like C let their functions/procedure
have side effects (eg, printing inside a function).
“function”).
Declarative languages like SQL are used for databases.
You write a description
description ofof the
theproblem
problemtotobe besolved,
solved,and
and
the computer figures out how to perform the the computation.
Object-oriented languages like Java manipulate
collections of objects.
objects. Objects
Objectshavehaveananinternal
internalstate
statewith
with
methods that
methods that query
query or
or modify
modify this
this state.
state.
C++ and Python
Python are
are languages
languages thatthatsupport
supportOOP, OOP,but but
don’t force the use of object-oriented features.
In functional programming languages like ML everything is
a function
function.Function
Functionbodies
bodieshave
haveonly
onlyaareturn
returnstatement
statement
with no side effects. Computation is achieved by nesting
calls of calls of calls of functions.
In Python everything is an object, even functions. So, in
many cases, most things can be functions. Python doesn’t
require functional programming, but it supports its use.
>>>
Comparing filter() and map()
print(filter.__doc__[:54]+filter.__doc__[88:
])
filter(function or None, iterable) --> filter
object
items of iterable for which function(item) is
true. If function is None, return the items
that are true.
>>> print(map.__doc__[:38]+map.__doc__[60:])
map(func, *iterables) --> map object
Fr ctur
Le
om e
Your typical mathematical function is written as: y = f(x)
5
But what is f( )? Any function. Perhaps sin(). In that case,
sin(x)
we write: y = sin(x).
Here the sine function maps
maps aa value,
value, x,
x, to
to aa new
new value,
value, y.y.
For example: y=sin(0) y=0,
if x=90, then y=1. y=1.
or y=sin(90)
y=sin(90)
You can look at an x value, move your finger vertically to
intersect the line, then horizontally to find the mapped-to
value.
A mapping is a concept from math
Fr ctur
Le
om e
sin(90)=1 is a mapping for just one value.
5
But what is the mapping, for all values?
That would be the set of all mappings.
A mapping is a concept from math
Fr ctur
Le
om e
sin(90)=1 is a mapping for just one value.
5
But what is the mapping, for all values?
That would be the set of all mappings.
Think
Think of
of it
it as
as aa look-up
look-up table:
table: 0 → 0.00000
10 → 0.17365
Q:How to make a table like this? 20 → 0.34202
30 → 0.50000
A:With map() 40 → 0.64279
... → ...
A mapping is a concept from math
Fr ctur
Le
om e
Think of it as a look-up table: 0 → 0.00000
5
10 → 0.17365
Q:How to make a table like this? 20 → 0.34202
30 → 0.50000
A:With map() 40 → 0.64279
Think of it as a look-up table: ... ...
0 →→ 0.00000
The sin( ) function takes one number and10returns
→ 0.17365
another one
Q:How to make
number. One a table
number. So it like this?
cannot 20 → a0.34202
understand list:
>>> from math import sin, radians 30 → 0.50000
A:With map()
>>> sin([0,radians(10), 40 → 0.64279
radians(20)])
Traceback (most recent call last): ... → ...
File "<stdin>", line 1, in <module>
TypeError: must be real number, not list
>>> # Use map() to apply a mapping to a list:
>>> map(sin,[0,radians(10), radians(20)])
[0.0, 0.17364817766693033, 0.3420201433256687]
A mapping is a concept from math
Fr ctur
Le
om e
Think of it as a look-up table: 0 → 0.00000
5
10 → 0.17365
Q:How to make a table like this? 20 → 0.34202
30 → 0.50000
A:With map() 40 → 0.64279
... → ...
>>> # Use map() to apply a mapping to a list:
>>> map(sin,[0,radians(10), radians(20)])
[0.0, 0.17364817766693033, 0.3420201433256687]
>>> #Can you ever have too many maps(), really?
>>> dict(zip(range(0,91,10),map(lambda
x:x/100000, ... map(round, map(lambda x:
\
100000*x,(map(sin, ... map(radians,
range(0,91,10)))))))))
>>> # Use map() to apply a mapping to a list:
{0: 0.0, 10: 0.17365, 20: 0.34202, 30: 0.5, 40:
>>> map(sin,[0,radians(10), radians(20)])
0.64279, 50: 0.76604, 60: 0.86603, 70: 0.93969,
[0.0, 0.17364817766693033, 0.3420201433256687]
map applies a given function to each
>>>
element
from math import factorial, gamma
>>> factorial(range(0,10)) #This won’t work
>>>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Theismath
TypeError:an integer requiredIt (got type
also has therange)
""
>>> list(map(factorial,range(0,10)))#map
>>> module has fixes it
(gamma) function.
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
the "n!" This relates to
>>> gamma(range(1,11))#This generalizes
>>> factorial
(factorial
Traceback (most recent call last): factorial by the
File "<stdin>", line階乘1,) in <module> formula:
function.
TypeError: must be real number, not n! range
= (n + 1)
>>> list(map(gamma,range(1,11)))#But it needs map
>>>
[1.0, 1.0, 2.0, 6.0, 24.0, 120.0, 720.0, 5040.0,
40320.0, 362880.0]
>>> list(map(int,map(gamma,range(1,11))))#cleaner
>>>
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
>>>
A map/lamda multi-list example:
map() can be applied to more than one list.
– The lists have to have the same length.
– The meaning is f(x,y) or f(x,y,z), etc.
>>> a=[1,2,3];b=[10,20,30];c=[100,200,300]
>>> list(map(lambda x,y:x+y, a,b))
[11, 22, 33]
>>> list(map(lambda x,y,z:x+y+z, a,b,c))
[111, 222, 333]
>>> list(map(lambda x,y,z:x+y-z, a,b,c))
[-89, -178, -267]
>>>
Another map( ) example:
% cat test.py
def fahrenheit(T): # ( 華氏度 )
return ((float(9)/5)*T + 32)
def celsius(T): # ( 攝氏溫度 )
return (float(5)/9)*(T-32)
temp = (36.5, 37, 37.5,39)
F = map(fahrenheit, temp); print(F)
F = list(F); print(F)
C = list(map(celsius, F)); print(C)
% python3 test.py
<map object at 0x6ffffc8be48>
[97.7, 98.60000000000001, 99.5, 102.2]
[36.5, 37.00000000000001, 37.5, 39.0]
%
A map( ) example with lambda
By using lambda, we wouldn't have had to
create the functions fahrenheit() and celsius() :
>>> c = [39.2, 36.5, 37.3, 37.8]
>>> f = map(lambda x:(float(9)/5)*x+ 32,c)
>>> f=[*f]; f
[102.56, 97.7, 99.14, 100.03999999999999]
>>>
>>> c2= map(lambda x:(float(5)/9)*(x-32),f)
>>> [*c2]
[39.2, 36.5, 37.300000000000004, 37.8]
>>>
Core functional programming tools
map(function, sequence)
– Apply the function to each item in the sequence.
– For multi-value functions, give multiple sequences.
– Return sequence of values returned by the function.
filter(function, sequence)
– Apply the function to each item in the sequence.
– The function's result is treated as a boolean.
– Return those items that pass the boolean filter.
functools.reduce(function, sequence)
– Apply the function to each item in the sequence.
– The function must take 2 arguments & return 1 value.
– That returned value then becomes the first argument to the
function on the next iteration (the second argument is the
next item in the sequence).
– Return 1 value, the final value returned by the function.
map(function, sequence(s))
– Apply the function to each item in the sequence.
– For multi-value functions, give multiple sequences.
– Return sequence of values returned by the function.
NAME
itertools - Functional tools for creating and using iterators.
DESCRIPTION
Infinite iterators:
count(start=0, step=1) start, start+step, start+2*step, ...
cycle(p) p0, p1, ... plast, p0, p1, ...
repeat(elem [,n]) elem, elem, elem, ... endlessly or up to n times
functools
reduce, partial, partialmethod
functools
reduce, partial, partialmethod
functools
reduce, partial, partialmethod
functools
reduce, partial, partialmethod
functools
reduce, partial, partialmethod
functools
reduce, partial, partialmethod
>>> print(partial.__doc__[:-1])
partial(func, *args, **keywords) – return
a new function with partial application
of the given arguments and keywords.
>>> indpnt=partial(print,'[\t',']')
>>> indpnt("Hello world!")
itertools
infinite(count, cycle, repeat)
variationsOnBuiltins(slice: islice, zip: zip_longest,
map: starmap, filter: filterfalse)
makesSmaller(compress, dropwhile, takewhile)
makesMultiple(groupby, tee)
combines(combinations, permutations, product, chain)
functools
reduce, partial, partialmethod
functools
reduce, partial, partialmethod
>>> indpnt=partial(print,'[\t',']')
>>> indpnt("Hello world!")
[ ] Hello world!
>>> copnt=partial(print,'\033[7;41;30m→',sep=
... '\033[3;30;42m ',end='\033[1;m\n')
>>> copnt('Hello','World',1,2,3,[*"abc"])
itertools
infinite(count, cycle, repeat)
variationsOnBuiltins(slice: islice, zip: zip_longest,
map: starmap, filter: filterfalse)
makesSmaller(compress, dropwhile, takewhile)
makesMultiple(groupby, tee)
combines(combinations, permutations, product, chain)
functools
reduce, partial, partialmethod
functools
reduce, partial, partialmethod
[ ] Hello world!
>>> copnt=partial(print,'\033[7;41;30m→',sep=
... '\033[3;30;42m ',end='\033[1;m\n')
>>> copnt('Hello','World',1,2,3,[*"abc"])
→ Hello World 1 2 3 ['a', 'b', 'c']
>>>
itertools
infinite(count, cycle, repeat)
variationsOnBuiltins(slice: islice, zip: zip_longest,
map: starmap, filter: filterfalse)
makesSmaller(compress, dropwhile, takewhile)
makesMultiple(groupby, tee)
combines(combinations, permutations, product, chain)
functools
reduce, partial, partialmethod
itertools
infinite(count, cycle, repeat)
variationsOnBuiltins(slice: islice, zip: zip_longest,
map: starmap, filter: filterfalse)
makesSmaller(compress, dropwhile, takewhile)
makesMultiple(groupby, tee)
combines(combinations, permutations, product, chain)
functools
reduce, partial, partialmethod
operator
ComparisonOps (lt, eq, le, ne, gt, ge)
LogicOps(not_, or_, and_, xor)
UnaryOps(abs, inv, neg, truth)
BinaryOps(concat, add, sub, mul, mod, truediv, pow)
ContainerOps(contains, index, indexOf, countOf)
itertools
functools.reduce(function, sequence)
Sl
id
infinite(count, cycle, repeat)
– Apply the function to each item in the sequence.
e
25
variationsOnBuiltins(slice:
– islice, zip: zip_longest,
The function must take 2 arguments & return 1 value.
– That returned valuemap: starmap,
becomes the 1st filter: filterfalse)
argument to the function
on the next iteration (2nd argument
makesSmaller(compress, is thetakewhile)
dropwhile, next sequence item).
– Return 1 value, the finaltee)
makesMultiple(groupby, value returned by the function.
>>> from functools import reduce
combines(combinations, permutations, product, chain)
>>> reduce(lambda x,y: x+y, range(9))
36
functools
>>> reduce(lambda x,y: x+y, map(str,range(9))))
reduce, partial, partialmethod
'012345678'
>>> print(reduce.__doc__[:46]+reduce.__doc__[47:])
operator
reduce(function, sequence [, initial]) -> value
ComparisonOps (lt, eq, le, ne, gt, ge)
Apply a function of 2 arguments cumulatively to the
items
LogicOps(not_, or_, and_,
of a sequence, xor) to right, so as to reduce
from left
the sequence to inv,
UnaryOps(abs, a single value. For example,
neg, truth)
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
BinaryOps(concat, add, sub, mul, mod, truediv, pow)
((((1+2)+3)+4)+5). If initial is present, it is placed
before
ContainerOps(contains, index, indexOf,
the items of the sequence in the countOf)
calculation, and
>>> reduce(lambda x,y: x+y, range(9))
itertools
functools.reduce(function, sequence)
36
infinite(count, cycle, repeat)
>>> –reduce(lambda
Apply the function x,y: x+y, item
to each map(str,range(9))))
in the sequence.
'012345678'
variationsOnBuiltins(slice: islice, zip:&zip_longest,
– The function must take 2 arguments return 1 value.
>>> –
That returned valuemap: starmap,
becomes the 1st filter: filterfalse)
argument to the function
on the next iteration (2nd argument
makesSmaller(compress, is thetakewhile)
dropwhile, next sequence item).
–Return 1 value, the finaltee)
makesMultiple(groupby, value returned by the function.
>>> from functools import reduce
combines(combinations, permutations, product, chain)
>>> reduce(lambda x,y: x+y, range(9))
36
functools
>>> reduce(lambda x,y: x+y, map(str,range(9))))
reduce, partial, partialmethod
'012345678'
>>> print(reduce.__doc__[:46]+reduce.__doc__[47:])
operator
reduce(function, sequence [, initial]) -> value
ComparisonOps (lt, eq, le, ne, gt, ge)
Apply a function of 2 arguments cumulatively to the
items
LogicOps(not_, or_, and_,
of a sequence, xor) to right, so as to reduce
from left
the sequence to inv,
UnaryOps(abs, a single value. For example,
neg, truth)
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
BinaryOps(concat, add, sub, mul, mod, truediv, pow)
((((1+2)+3)+4)+5). If initial is present, it is placed
before
ContainerOps(contains, index, indexOf,
the items of the sequence in the countOf)
calculation, and
>>> reduce(lambda x,y: x+y, range(9))
itertools
36
infinite(count, cycle, repeat)
>>> reduce(lambda x,y: x+y, map(str,range(9))))
'012345678'
variationsOnBuiltins(slice: islice, zip: zip_longest,
>>> sum(range(9)) map: starmap, filter: filterfalse)
makesSmaller(compress, dropwhile, takewhile)
makesMultiple(groupby, tee)
combines(combinations, permutations, product, chain)
functools
reduce, partial, partialmethod
operator
ComparisonOps (lt, eq, le, ne, gt, ge)
LogicOps(not_, or_, and_, xor)
UnaryOps(abs, inv, neg, truth)
BinaryOps(concat, add, sub, mul, mod, truediv, pow)
ContainerOps(contains, index, indexOf, countOf)
>>> reduce(lambda x,y: x+y, range(9))
itertools
36
infinite(count, cycle, repeat)
>>> reduce(lambda x,y: x+y, map(str,range(9))))
'012345678'
variationsOnBuiltins(slice: islice, zip: zip_longest,
>>> sum(range(9)) map: starmap, filter: filterfalse)
36
makesSmaller(compress,
>>> try: sum("a","b") dropwhile, takewhile)
... except: print("Can't tee)
makesMultiple(groupby, use sum() on strings")
...
combines(combinations,
Can't use sum() on strings permutations, product, chain)
>>> import operator as op
functools
>>>
reduce, partial, partialmethod
reduce(op.add,map(str,range(9))),reduce(op.add,range(9
))
>>>
operator
('012345678', 36)
>>> reduce(op.concat,
ComparisonOps map(str,range(9)))
(lt, eq, le, ne, gt, ge)
'012345678'
...
LogicOps(not_, or_, and_, xor)
>>>
... try: reduce(op.concat, range(9))
UnaryOps(abs,
... except: print("Can't use concat() on numbers")
inv, neg, truth)
>>>
BinaryOps(concat,
concat on add
add, sub, mul, mod, truediv, pow)
Can't use concat() numbers
ContainerOps(contains,
>>> "".join(map(str,range(9))) index, indexOf, countOf)
#BTW, this also worx
collections # These extend the 7(or 9) built-in data types
namedtuple, deque, defaultdict, OrderedDict, Counter
>>> print(collections.__doc__)
This module implements specialized container datatypes providing alternatives
to Python's general purpose built-in containers, dict, list, set, and tuple.
* namedtuple factory function for creating tuple subclasses with named fields
* deque list-like container with fast appends and pops on either end
* ChainMap dict-like class for creating a single view of multiple mappings
* Counter dict subclass for counting hashable objects
* OrderedDict dict subclass that remembers the order entries were added
* defaultdict dict subclass that calls a factory function to get missing values
* UserDict wrapper around dictionary objects for easier dict subclassing
* UserList wrapper around list objects for easier list subclassing
* UserString wrapper around string objects for easier string subclassing
>>>
https://docs.python.org/3/library/collections.html
collections # These extend the 7(or 9) built-in data types
namedtuple, deque, defaultdict, OrderedDict, Counter