• Like
(2014-04-16) [Garoa HC] Strategy
Upcoming SlideShare
Loading in...5
×

(2014-04-16) [Garoa HC] Strategy

  • 247 views
Uploaded on

Strategy (Design Pattern) e seu uso com dicionário e Multiton

Strategy (Design Pattern) e seu uso com dicionário e Multiton

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
247
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
1
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini Strategy (Design Pattern)Strategy (Design Pattern) e seu uso com dicionário e Multitone seu uso com dicionário e Multiton Segunda reunião em 2014 do grupo de estudos deSegunda reunião em 2014 do grupo de estudos de Design patterns em linguagens dinâmicasDesign patterns em linguagens dinâmicas nono Garoa Hacker ClubeGaroa Hacker Clube Slides com a preparação deSlides com a preparação de Danilo J. S. BelliniDanilo J. S. Bellini para discussão durante reuniãopara discussão durante reunião 2014-04-162014-04-16 Código dos slides disponível em: https://github.com/danilobellini/design_patterns
  • 2. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini ProblemaProblema ● Muitas soluções para um mesmo problemaMuitas soluções para um mesmo problema – Ordenação (sort), programação não-linear,Ordenação (sort), programação não-linear, reconhecimento de padrões, otimização,reconhecimento de padrões, otimização, processamento de sinais, …processamento de sinais, … – Família de algoritmosFamília de algoritmos ● Decisão em tempo de execução do algoritmo aDecisão em tempo de execução do algoritmo a ser utilizadoser utilizado
  • 3. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini StrategyStrategy ● 3 conceitos:3 conceitos: – InterfaceInterface – EstratégiasEstratégias – Contexto (de uso)Contexto (de uso)
  • 4. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini UML?! Muito chato! Cadê o código?UML?! Muito chato! Cadê o código? Não é nested o suficiente? #!/usr/bin/env python3 from abc import ABCMeta, abstractmethod class Estratégia(metaclass=ABCMeta): @abstractmethod def executar(self, a, b): # Dois inteiros pass class Soma(Estratégia): def executar(self, a, b): return a + b class Subtração(Estratégia): def executar(self, a, b): return a - b class Multiplicação(Estratégia): def executar(self, a, b): return a * b class Contexto: def __init__(self, estratégia, símbolo): self.estratégia = estratégia self.símbolo = símbolo def tarefa(self, a, b): resultado = self.estratégia.executar(a, b) args = (a, self.símbolo, b, resultado) print("{} {} {} = {}".format(*args)) #!/usr/bin/env python3 from abc import ABCMeta, abstractmethod class Estratégia(metaclass=ABCMeta): @abstractmethod def executar(self, a, b): # Dois inteiros pass class Soma(Estratégia): def executar(self, a, b): return a + b class Subtração(Estratégia): def executar(self, a, b): return a - b class Multiplicação(Estratégia): def executar(self, a, b): return a * b class Contexto: def __init__(self, estratégia, símbolo): self.estratégia = estratégia self.símbolo = símbolo def tarefa(self, a, b): resultado = self.estratégia.executar(a, b) args = (a, self.símbolo, b, resultado) print("{} {} {} = {}".format(*args)) if __name__ == "__main__": Contexto(Soma(), "+").tarefa(22, 3) ctx = Contexto(Subtração(), "-") ctx.tarefa(22, 3) ctx.estratégia = Multiplicação() ctx.símbolo = "*" ctx.tarefa(22, 3) if __name__ == "__main__": Contexto(Soma(), "+").tarefa(22, 3) ctx = Contexto(Subtração(), "-") ctx.tarefa(22, 3) ctx.estratégia = Multiplicação() ctx.símbolo = "*" ctx.tarefa(22, 3) strategy_0.py
  • 5. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini Burocracia...é necessária?Burocracia...é necessária? ● Definição de classes para cada algoritmoDefinição de classes para cada algoritmo – Mais de uma instância de um único algoritmo?Mais de uma instância de um único algoritmo? – Memória (efeito colaterais)?Memória (efeito colaterais)? – Instante da instanciação?Instante da instanciação? ● Definição explícita da interfaceDefinição explícita da interface – Tipos estáticos e explícitos?Tipos estáticos e explícitos? – Quantidades/nomes de argumentos sempreQuantidades/nomes de argumentos sempre idênticos?idênticos? ● Orientação a objetos?Orientação a objetos? Não!Não!
  • 6. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini InterfaceInterface em Pythonem Python ● Duck typingDuck typing ““When I see a bird thatWhen I see a bird that ● walks like a duck andwalks like a duck and ● swims like a duck andswims like a duck and ● quacks like a duck,quacks like a duck, I call that bird a duck.”I call that bird a duck.” ● ABC (Abstract Base Classes)ABC (Abstract Base Classes) – Dunder __subclasshook__Dunder __subclasshook__
  • 7. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini #!/usr/bin/env python3 class Soma: def executar(self, a, b): return a + b class Subtração: def executar(self, a, b): return a - b class Multiplicação: def executar(self, a, b): return a * b class Contexto: def __init__(self, estratégia, símbolo): self.estratégia = estratégia self.símbolo = símbolo def tarefa(self, a, b): resultado = self.estratégia.executar(a, b) args = (a, self.símbolo, b, resultado) print("{} {} {} = {}".format(*args)) #!/usr/bin/env python3 class Soma: def executar(self, a, b): return a + b class Subtração: def executar(self, a, b): return a - b class Multiplicação: def executar(self, a, b): return a * b class Contexto: def __init__(self, estratégia, símbolo): self.estratégia = estratégia self.símbolo = símbolo def tarefa(self, a, b): resultado = self.estratégia.executar(a, b) args = (a, self.símbolo, b, resultado) print("{} {} {} = {}".format(*args)) if __name__ == "__main__": Contexto(Soma(), "+").tarefa(22, 3) ctx = Contexto(Subtração(), "-") ctx.tarefa(22, 3) ctx.estratégia = Multiplicação() ctx.símbolo = "*" ctx.tarefa(22, 3) if __name__ == "__main__": Contexto(Soma(), "+").tarefa(22, 3) ctx = Contexto(Subtração(), "-") ctx.tarefa(22, 3) ctx.estratégia = Multiplicação() ctx.símbolo = "*" ctx.tarefa(22, 3) Sem classe abstrataSem classe abstrata (interface implícita)(interface implícita) strategy_1.py
  • 8. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini #!/usr/bin/env python3 from abc import ABCMeta, abstractmethod class Estratégia(metaclass=ABCMeta): @abstractmethod def executar(self, a, b): # Dois inteiros pass @classmethod def __subclasshook__(cls, C): return any("executar" in vars(B) for B in C.mro()) or NotImplemented class Soma: def executar(self, a, b): return a + b print(isinstance(Soma(), Estratégia)) # True print(issubclass(Soma, Estratégia)) # True #!/usr/bin/env python3 from abc import ABCMeta, abstractmethod class Estratégia(metaclass=ABCMeta): @abstractmethod def executar(self, a, b): # Dois inteiros pass @classmethod def __subclasshook__(cls, C): return any("executar" in vars(B) for B in C.mro()) or NotImplemented class Soma: def executar(self, a, b): return a + b print(isinstance(Soma(), Estratégia)) # True print(issubclass(Soma, Estratégia)) # True Subclass HookSubclass Hook subclasshook.py In [5]: B.mro() Out[5]: [__main__.B, __main__.A, builtins.object] In [6]: D.mro() # MRO = Method Resolution Order Out[6]: [__main__.D, __main__.B, __main__.C, __main__.A, builtins.object] In [7]: vars(B) # Atributos (métodos, propriedades, etc.) Out[7]: dict_proxy({'__module__': '__main__', '__doc__': None}) In [5]: B.mro() Out[5]: [__main__.B, __main__.A, builtins.object] In [6]: D.mro() # MRO = Method Resolution Order Out[6]: [__main__.D, __main__.B, __main__.C, __main__.A, builtins.object] In [7]: vars(B) # Atributos (métodos, propriedades, etc.) Out[7]: dict_proxy({'__module__': '__main__', '__doc__': None}) In [1]: class A: pass In [2]: class B(A): pass In [3]: class C(A): pass In [4]: class D(B, C): pass In [1]: class A: pass In [2]: class B(A): pass In [3]: class C(A): pass In [4]: class D(B, C): pass O que é MRO?
  • 9. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini EstratégiaEstratégia ● Qualquer callableQualquer callable – Método, função, __call__, operadores, etc.Método, função, __call__, operadores, etc. ● Funções como objetos de segunda classeFunções como objetos de segunda classe – Utilização do método de um objetosUtilização do método de um objetos – Classes para possibilitar objetosClasses para possibilitar objetos – InstanciaçãoInstanciação ● Python, Ruby, JavaScript, …Python, Ruby, JavaScript, … – Funções de primeira classeFunções de primeira classe – Funções de ordem superiorFunções de ordem superior – Fechamentos (closures)Fechamentos (closures)
  • 10. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini #!/usr/bin/env python3 def soma(a, b): return a + b def subtração(a, b): return a - b def multiplicação(a, b): return a * b class Contexto: def __init__(self, estratégia, símbolo): self.estratégia = estratégia self.símbolo = símbolo def tarefa(self, a, b): resultado = self.estratégia(a, b) args = (a, self.símbolo, b, resultado) print("{} {} {} = {}".format(*args)) #!/usr/bin/env python3 def soma(a, b): return a + b def subtração(a, b): return a - b def multiplicação(a, b): return a * b class Contexto: def __init__(self, estratégia, símbolo): self.estratégia = estratégia self.símbolo = símbolo def tarefa(self, a, b): resultado = self.estratégia(a, b) args = (a, self.símbolo, b, resultado) print("{} {} {} = {}".format(*args)) if __name__ == "__main__": Contexto(soma, "+").tarefa(22, 3) ctx = Contexto(subtração, "-") ctx.tarefa(22, 3) ctx.estratégia = multiplicação ctx.símbolo = "*" ctx.tarefa(22, 3) if __name__ == "__main__": Contexto(soma, "+").tarefa(22, 3) ctx = Contexto(subtração, "-") ctx.tarefa(22, 3) ctx.estratégia = multiplicação ctx.símbolo = "*" ctx.tarefa(22, 3) Funções de primeira classe!Funções de primeira classe! strategy_2.py ● Funções comoFunções como valores (ou objetos)valores (ou objetos) ● ““Callback”Callback” ● ““Handler”Handler”
  • 11. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini PythonPython lambda e namedtuplelambda e namedtuple #!/usr/bin/env python3 from collections import namedtuple Strategy = namedtuple("Strategy", ["func", "symbol"]) sum = lambda a, b: a + b sub = lambda a, b: a - b mul = lambda a, b: a * b apply = lambda st, a, b: st.func(a, b) strategies = [Strategy(sum, "+"), Strategy(sub, "-"), Strategy(mul, "*")] for st in strategies: print("2 %c 3 = %d" % (st.symbol, apply(st, 2, 3))) print("7 %c 5 = %d" % (st.symbol, apply(st, 7, 5))) #!/usr/bin/env python3 from collections import namedtuple Strategy = namedtuple("Strategy", ["func", "symbol"]) sum = lambda a, b: a + b sub = lambda a, b: a - b mul = lambda a, b: a * b apply = lambda st, a, b: st.func(a, b) strategies = [Strategy(sum, "+"), Strategy(sub, "-"), Strategy(mul, "*")] for st in strategies: print("2 %c 3 = %d" % (st.symbol, apply(st, 2, 3))) print("7 %c 5 = %d" % (st.symbol, apply(st, 7, 5))) strategy_3.py
  • 12. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini CC #include <stdio.h> typedef int (*BinaryOpPtr)(int, int); typedef struct{ BinaryOpPtr func; char symbol; } Strategy; int sum(int a, int b){ return a + b; } int sub(int a, int b){ return a - b; } int mul(int a, int b){ return a * b; } int apply(Strategy st, int a, int b){ return st.func(a, b); } Strategy strategies[] = {{sum, '+'}, {sub, '-'}, {mul, '*'}}; int main(){ Strategy st; int idx; for(idx = 0; idx < 3; idx++){ st = strategies[idx]; printf("2 %c 3 = %dn", st.symbol, apply(st, 2, 3)); printf("7 %c 5 = %dn", st.symbol, apply(st, 7, 5)); } return 0; } #include <stdio.h> typedef int (*BinaryOpPtr)(int, int); typedef struct{ BinaryOpPtr func; char symbol; } Strategy; int sum(int a, int b){ return a + b; } int sub(int a, int b){ return a - b; } int mul(int a, int b){ return a * b; } int apply(Strategy st, int a, int b){ return st.func(a, b); } Strategy strategies[] = {{sum, '+'}, {sub, '-'}, {mul, '*'}}; int main(){ Strategy st; int idx; for(idx = 0; idx < 3; idx++){ st = strategies[idx]; printf("2 %c 3 = %dn", st.symbol, apply(st, 2, 3)); printf("7 %c 5 = %dn", st.symbol, apply(st, 7, 5)); } return 0; } O mesmo exemplo do slide anterior strategy.c
  • 13. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini ScipyScipy (e muitos outros)(e muitos outros) ● Duas maneiras diferentes de resolver o problema:Duas maneiras diferentes de resolver o problema: – Diversas funções dispersas com assinatura similar, usar noDiversas funções dispersas com assinatura similar, usar no contextocontexto ● e.g. funções do scipy.optimizee.g. funções do scipy.optimize – String com o nome da estratégia como parâmetroString com o nome da estratégia como parâmetro ● e.g. projeto de filtros IIR com o scipy.signal.iirdesigne.g. projeto de filtros IIR com o scipy.signal.iirdesign – ftype = “ellip”ftype = “ellip” → Elíptico→ Elíptico – ftype = “butter”ftype = “butter” → Butterworth→ Butterworth – ftype = “cheby1”ftype = “cheby1” → Chebyshev I→ Chebyshev I – ftype = “cheby2”ftype = “cheby2” → Chebyshev II→ Chebyshev II – ftype = “bessel”ftype = “bessel” → Bessel→ Bessel – Saída chaveada pela stringSaída chaveada pela string “ba”“ba” ouou “zpk”“zpk” no parâmetro de entradano parâmetro de entrada outputoutput Em alguns casos (e.g. fmin), é possível usar os nomes com o built-in dir para possíveis consultas Estratégias existentes apresentadas em docstring
  • 14. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini ContextoContexto ● Completamente aberto, basta que utilize ouCompletamente aberto, basta que utilize ou possa utilizar a estratégiapossa utilizar a estratégia – ““Executa o algoritmo”Executa o algoritmo” ● Outros possíveis requisitos, reflection “CRUD”:Outros possíveis requisitos, reflection “CRUD”: – Conhecer/consultar todas as estratégiasConhecer/consultar todas as estratégias – Varrer por todas as estratégiasVarrer por todas as estratégias – Modificar, remover ou criar novas estratégiasModificar, remover ou criar novas estratégias
  • 15. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini DicionárioDicionário (Mapping / Hash / Vetor associativo)(Mapping / Hash / Vetor associativo) ● Pares chave-valorPares chave-valor ● Sem “ordenação”Sem “ordenação” ● VariantesVariantes – OrderedDictOrderedDict – defaultdictdefaultdict ● 3 métodos para iterar:3 métodos para iterar: – Dict.keys()Dict.keys() – Dict.values()Dict.values() – Dict.items()Dict.items() → Pares chave, valor→ Pares chave, valor #!/usr/bin/env python3 strategies = { "+": lambda a, b: a + b, "-": lambda a, b: a - b, "*": lambda a, b: a * b, } for key, value in strategies.items(): print("2 %c 3 = %d" % (key, value(2, 3))) print("7 %c 5 = %d" % (key, value(7, 5))) #!/usr/bin/env python3 strategies = { "+": lambda a, b: a + b, "-": lambda a, b: a - b, "*": lambda a, b: a * b, } for key, value in strategies.items(): print("2 %c 3 = %d" % (key, value(2, 3))) print("7 %c 5 = %d" % (key, value(7, 5))) strategy_4.py No Python 3, devolvem iteráveis. No Python 2, devolvem listas, mas os métodos com prefixo “iter” (e.g. “dict.iteritems()”) devolvem iteradores. Função (anônima) como valor
  • 16. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini E quando o elemento com aE quando o elemento com a “chave” não está no dicionário?“chave” não está no dicionário? ● __missing____missing__ – Criar elemento?Criar elemento? – Responder?Responder? ● Há análogos:Há análogos: – __getitem____getitem__ – __getattr____getattr__ #!/usr/bin/env python3 class MeuDicionário(dict): def __missing__(self, chave): if chave.strip() != chave: valor = self[chave.strip()] self[chave] = valor return valor raise KeyError("Not Found") estratégias = MeuDicionário([ ("+", lambda a, b: a + b), ("-", lambda a, b: a - b), ("*", lambda a, b: a * b), ]) for símbolo in ["+", " +", " - ", "n* n"]: função = estratégias[símbolo] print("2 %s 3 = %d" % (símbolo, função(2, 3))) print("7 %s 5 = %d" % (símbolo, função(7, 5))) print(estratégias["/"]) #!/usr/bin/env python3 class MeuDicionário(dict): def __missing__(self, chave): if chave.strip() != chave: valor = self[chave.strip()] self[chave] = valor return valor raise KeyError("Not Found") estratégias = MeuDicionário([ ("+", lambda a, b: a + b), ("-", lambda a, b: a - b), ("*", lambda a, b: a * b), ]) for símbolo in ["+", " +", " - ", "n* n"]: função = estratégias[símbolo] print("2 %s 3 = %d" % (símbolo, função(2, 3))) print("7 %s 5 = %d" % (símbolo, função(7, 5))) print(estratégias["/"]) missing.py
  • 17. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini MultitonMultiton ● Multi + singletonMulti + singleton – ““Registro deRegistro de singletons”singletons” – LazyLazy ● Similar aoSimilar ao dicionáriodicionário – Valores definidosValores definidos (ou instanciados)(ou instanciados) no primeiro usono primeiro uso ● ““Cache”Cache” #!/usr/bin/env python3 op = { "+": lambda a, b: a + b, "-": lambda a, b: a - b, "*": lambda a, b: a * b, } class MeuDicionário(dict): def __missing__(self, chave): if chave[0] in op: b = int(chave[1:]) func = op[chave[0]] resultado = lambda a: func(a, b) else: a = int(chave[:-1]) func = op[chave[-1]] resultado = lambda b: func(a, b) self[chave] = resultado return resultado estratégias = MeuDicionário() for símbolo in ["+2", "5-", "-3", "4*", "+2"]: função = estratégias[símbolo] print("2, %s -> %d" % (símbolo, função(2))) print("-1, %s -> %d" % (símbolo, função(-1))) print("7, %s -> %d" % (símbolo, função(7))) #!/usr/bin/env python3 op = { "+": lambda a, b: a + b, "-": lambda a, b: a - b, "*": lambda a, b: a * b, } class MeuDicionário(dict): def __missing__(self, chave): if chave[0] in op: b = int(chave[1:]) func = op[chave[0]] resultado = lambda a: func(a, b) else: a = int(chave[:-1]) func = op[chave[-1]] resultado = lambda b: func(a, b) self[chave] = resultado return resultado estratégias = MeuDicionário() for símbolo in ["+2", "5-", "-3", "4*", "+2"]: função = estratégias[símbolo] print("2, %s -> %d" % (símbolo, função(2))) print("-1, %s -> %d" % (símbolo, função(-1))) print("7, %s -> %d" % (símbolo, função(7))) multiton.py Closure
  • 18. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini AudioLazyAudioLazy ● StrategyDict (dicionário de estratégias)StrategyDict (dicionário de estratégias) – IterávelIterável ● Padrão por estratégias (valores)Padrão por estratégias (valores) – Múltiplas chaves (nomes)Múltiplas chaves (nomes) ● e.g.e.g. window[“rectangular”] is window[“rect”]window[“rectangular”] is window[“rect”] → True→ True – Acesso como atributosAcesso como atributos ● e.g.e.g. lowpass.pole_exp(pi/7)lowpass.pole_exp(pi/7) – Estratégia padrão do dicionárioEstratégia padrão do dicionário ● Consultável no atributo “default”Consultável no atributo “default” ● e.g.e.g. lowpass(pi/7)lowpass(pi/7) equivale aequivale a lowpass.pole(pi/7)lowpass.pole(pi/7) Docstrings com “resumos” automáticos das docstrings das estratégias
  • 19. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini Uso da StrategyDict na AudioLazyUso da StrategyDict na AudioLazy In [1]: import audiolazy In [2]: from audiolazy import StrategyDict In [3]: [name for name in dir(audiolazy) ...: if isinstance(getattr(audiolazy, name), StrategyDict)] Out[3]: ['accumulate', 'almost_eq', 'chain', 'chunks', 'comb', 'envelope', 'erb', 'float_str', 'gammatone', 'highpass', 'izip', 'lagrange', 'lowpass', 'lpc', 'maverage', 'resonator', 'window'] In [4]: len(_) # Total de nomes de instâncias de StrategyDict na AudioLazy Out[4]: 17 In [5]: len(audiolazy.window) # Todos atualmente com pelo menos 2 estratégias Out[5]: 6 In [1]: import audiolazy In [2]: from audiolazy import StrategyDict In [3]: [name for name in dir(audiolazy) ...: if isinstance(getattr(audiolazy, name), StrategyDict)] Out[3]: ['accumulate', 'almost_eq', 'chain', 'chunks', 'comb', 'envelope', 'erb', 'float_str', 'gammatone', 'highpass', 'izip', 'lagrange', 'lowpass', 'lpc', 'maverage', 'resonator', 'window'] In [4]: len(_) # Total de nomes de instâncias de StrategyDict na AudioLazy Out[4]: 17 In [5]: len(audiolazy.window) # Todos atualmente com pelo menos 2 estratégias Out[5]: 6
  • 20. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini strategy_sort.py #!/usr/bin/env python3 from operator import itemgetter from audiolazy import StrategyDict sort = StrategyDict("sort") @sort.strategy("slow", "bad") def sort(data): for idx, el in enumerate(data): idx_min, el_min = min(enumerate(data[idx:], idx), key=itemgetter(1)) data[idx], data[idx_min] = el_min, el @sort.strategy("bubble") def sort(data): . . . @sort.strategy("merge") def sort(data): . . . #!/usr/bin/env python3 from operator import itemgetter from audiolazy import StrategyDict sort = StrategyDict("sort") @sort.strategy("slow", "bad") def sort(data): for idx, el in enumerate(data): idx_min, el_min = min(enumerate(data[idx:], idx), key=itemgetter(1)) data[idx], data[idx_min] = el_min, el @sort.strategy("bubble") def sort(data): . . . @sort.strategy("merge") def sort(data): . . . if __name__ == "__main__": from random import shuffle data = list(range(30)) print(sort.default.__name__) # slow (primeira) print() print(sort.bubble is sort["bubble"]) # True print() print(sort) # As 3 estratégias for st in sort: print() shuffle(data) print(data) # Scrambled st(data) print(data) # [0, 1, 2, ...] if __name__ == "__main__": from random import shuffle data = list(range(30)) print(sort.default.__name__) # slow (primeira) print() print(sort.bubble is sort["bubble"]) # True print() print(sort) # As 3 estratégias for st in sort: print() shuffle(data) print(data) # Scrambled st(data) print(data) # [0, 1, 2, ...] Contexto Exemplo: Ordenação com um StrategyDict ● “slow”: Ordenar coletando valores mínimos ● “bubble”: Alone bubble sort ● “merge”: Merge sort
  • 21. 2014-04-16 – Strategy – Design patterns em linguagens dinâmicas – Danilo J. S. Bellini Fim!Fim! Obrigado =) Repositório com o código dos slides: https://github.com/danilobellini/design_patterns