programação funcional em python
DESCRIPTION
Programação Funcional em Python Apresentada na Python Brasil 2012 com Hugo Lopes TavaresTRANSCRIPT
PROGRAMAÇÃOFUNCIONAL EM PYTHON
Hugo Tavares
Juarez Bochi
globo.com
THE ELEMENTS OF PROGRAMMINGPrimitive Expressions
Means of CombinationMeans of Abstraction
PARADIGMASImperativo
LógicoOrientado a Objetos
Funcional
PYTHON É FUNCIONAL?
FIRST CLASS FUNCTIONHIGHER-ORDER FUNCTION
HIGHER-ORDER FUNCTION - SORT BYpessoas = [{'nome': 'Adolfo', 'estado': 'MG'}, {'nome': 'Pedro', 'estado': 'RS'}, {'nome': 'Maria', 'estado': 'AC'}]
def por_estado(pessoa1, pessoa2): return cmp(pessoa1['estado'], pessoa2['estado'])
>>> pprint.pprint(sorted(pessoas, cmp=por_estado))[{'estado': 'AC', 'nome': 'Maria'}, {'estado': 'MG', 'nome': 'Adolfo'}, {'estado': 'RS', 'nome': 'Pedro'}]
HIGHER-ORDER FUNCTION - DECORATORdef memoize(fn): cache = {} def newfn(arg): if arg in cache: return cache[arg] else: cache[arg] = fn(arg) return cache[arg] return newfn
APLICAÇÃO DECORATORdef fib(n): if n in (1, 2): return 1 return fib(n - 1) + fib(n - 2)
def fast_fib(n): if n in (1, 2): return 1 return fast_fib(n - 1) + fast_fib(n - 2)
fast_fib = memoize(fast_fib)
if __name__ == '__main__': print(timeit.timeit("import fib; fib.fib(35)", number=1)) print(timeit.timeit("import fib; fib.fast_fib(35)", number=1))
# 3.71057915688# 0.000109195709229
RECURSÃO - MOEDASdef troco(n, moedas): if n == 0: return 1 elif n < 0 or len(moedas) == 0: return 0 else: return troco(n, moedas[1:]) + \ troco(n - moedas[0], moedas)
>>> troco(3, [1, 2])2>>> troco(100, [50, 7])1>>> troco(10, [50, 10, 5, 1, .50, .25, .10, .5, .1])1153
RECURSÃO - FATORIALdef fat(n): if n == 0: return 1 else: return n * fat(n - 1)
"""fat(5)5 * fat(4)5 * (4 * fat(3))5 * (4 * (3 * fat(2)))5 * (4 * (3 * (2 * fat(1)))5 * (4 * (3 * (2 * (1 * fat(0)))5 * (4 * (3 * (2 * (1 * 1))5 * (4 * (3 * (2 * 1))5 * (4 * (3 * 2))5 * (4 * 6)5 * 24120"""
TAIL RECURSIONdef fat(n, acc=1): if n == 0: return acc else: return fat(n - 1, acc * n)
"""fat(5, 1)fat(4, 5)fat(3, 20)fat(2, 60)fat(1, 120)fat(0, 120)120"""
>>> fat(1000) File "", line 5, in fat ...RuntimeError: maximum recursion depth exceeded
TAIL RECURSION OPTIMIZATIONfrom optimization import tail_call_optimized
@tail_call_optimizeddef fat(n, acc=1): if n <= 1: return acc else: return fat(n - 1, acc * n)
>>> fat(1000)402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223
@tail_call_optimized
CURRYINGdef somador(a): def soma(b): return a + b return soma
>>> somador(1)<function soma at 0x100499f50>>>> somador(1)(2)3>>> incr = somador(1)>>> incr(2)3>>> incr(3)4
CURRYING & PARTIALSdef partial(funcao, argumento): def fn(arg): return funcao(argumento, arg) return fn
def to_tag(tag, texto): return "<{tag}>{texto}</{tag}>".format(tag=tag, texto=texto)
negrito = partial(to_tag, 'b')italico = partial(to_tag, 'i')
>>> negrito(italico("oi, python brasil"))"<b><i>oi, python brasil</i></b>"
DATA ABSTRACTION
DATA ABSTRACTIONclass Zero(Natural): def __init__(self): pass
def __repr__(self): return "0"
def __add__(self, other): return other
DATA ABSTRACTIONclass Natural(object): def __init__(self, anterior): self.anterior = anterior
def __repr__(self): return repr(self.anterior) + " + 1"
def __add__(self, other): return self.anterior + other.sucessor()
def sucessor(self): return Natural(anterior=self)
DATA ABSTRACTION>>> zero = Zero()>>> um = zero.sucessor()>>> dois = um.sucessor()>>> um0 + 1>>> dois0 + 1 + 1>>> um + dois0 + 1 + 1 + 1
STOP WRITING CLASSESJack Diederich, PyCon US 2012
http://pyvideo.org/video/880/stop-writing-classes
STOP WRITING CLASSESclass Greeting(object): def __init__(self, greeting="hello"): self.greeting = greeting
def greet(self, name): return "{greet}! {name}".format(greet=self.greeting, name)
>>> hola = Greeting("hola")>>> hola.greet("bob")"hola! bob"
LAZYNESS & GENERATORS
LAZYNESS & GENERATORSdef naturais(): i = 0 while True: yield i i += 1
def pares(): return ifilter(lambda x: x % 2 == 0, naturais())
>>> sum(take(pares(), 10))90
RESUMOCódigo compreensível
Fácil de testarFácil de manterFácil de escalar
REFERÊNCIASStructure and Interpretation of Computer Programs
Functional Programming Principles in ScalaStop Writing Classes" - PyCon US 2012
Códigos usados na palestra: