Skip to content

Commit fd11bb8

Browse files
committed
novos exemplos do curso na Novatec
1 parent 6c4d90e commit fd11bb8

File tree

13 files changed

+708
-1
lines changed

13 files changed

+708
-1
lines changed

decorator/clockdeco.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# clockdeco.py
22

33
import time
4-
4+
import functools
55

66
def clock(func):
7+
@functools.wraps(func)
78
def clocked(*args):
89
t0 = time.time()
910
result = func(*args)

novatec/adaptador.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
"""
3+
4+
>>> p = Parede()
5+
>>> f = Fonte(p)
6+
>>> a = Aparelho(f)
7+
>>> a.ligar()
8+
>>> a.ligado
9+
True
10+
11+
"""
12+
13+
class Aparelho:
14+
15+
def __init__(self, fonte=None):
16+
self.fonte = fonte
17+
self.ligado = False
18+
19+
def ligar(self):
20+
if self.fonte.corrente_continua():
21+
self.ligado = True
22+
23+
class Parede:
24+
25+
def corrente_alternada(self):
26+
return True
27+
28+
class Fonte:
29+
30+
def __init__(self, parede):
31+
self.parede = parede
32+
33+
def converter(self):
34+
return self.parede.corrente_alternada()
35+
36+
def corrente_continua(self):
37+
return self.converter()

novatec/borg.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
class Borg:
3+
_estado_compartilhado = {}
4+
5+
def __new__(cls, *args, **kwargs):
6+
novo_borg = super().__new__(cls, *args, **kwargs)
7+
novo_borg.__dict__ = cls._estado_compartilhado
8+
return novo_borg

novatec/classic_strategy.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# classic_strategy.py
2+
# Strategy pattern -- classic implementation
3+
4+
"""
5+
# BEGIN CLASSIC_STRATEGY_TESTS
6+
7+
>>> joe = Customer('John Doe', 0) # <1>
8+
>>> ann = Customer('Ann Smith', 1100)
9+
>>> cart = [LineItem('banana', 4, .5), # <2>
10+
... LineItem('apple', 10, 1.5),
11+
... LineItem('watermellon', 5, 5.0)]
12+
>>> Order(joe, cart, FidelityPromo()) # <3>
13+
<Order total: 42.00 due: 42.00>
14+
>>> Order(ann, cart, FidelityPromo()) # <4>
15+
<Order total: 42.00 due: 39.90>
16+
>>> banana_cart = [LineItem('banana', 30, .5), # <5>
17+
... LineItem('apple', 10, 1.5)]
18+
>>> Order(joe, banana_cart, BulkItemPromo()) # <6>
19+
<Order total: 30.00 due: 28.50>
20+
>>> long_order = [LineItem(str(item_code), 1, 1.0) # <7>
21+
... for item_code in range(10)]
22+
>>> Order(joe, long_order, LargeOrderPromo()) # <8>
23+
<Order total: 10.00 due: 9.30>
24+
>>> Order(joe, cart, LargeOrderPromo())
25+
<Order total: 42.00 due: 42.00>
26+
27+
# END CLASSIC_STRATEGY_TESTS
28+
"""
29+
# BEGIN CLASSIC_STRATEGY
30+
31+
from abc import ABC, abstractmethod
32+
from collections import namedtuple
33+
34+
Customer = namedtuple('Customer', 'name fidelity')
35+
36+
37+
class LineItem:
38+
39+
def __init__(self, product, quantity, price):
40+
self.product = product
41+
self.quantity = quantity
42+
self.price = price
43+
44+
def total(self):
45+
return self.price * self.quantity
46+
47+
48+
class Order: # the Context
49+
50+
def __init__(self, customer, cart, promotion=None):
51+
self.customer = customer
52+
self.cart = list(cart)
53+
self.promotion = promotion
54+
55+
def total(self):
56+
if not hasattr(self, '__total'):
57+
self.__total = sum(item.total() for item in self.cart)
58+
return self.__total
59+
60+
def due(self):
61+
if self.promotion is None:
62+
discount = 0
63+
else:
64+
discount = self.promotion.discount(self)
65+
return self.total() - discount
66+
67+
def __repr__(self):
68+
fmt = '<Order total: {:.2f} due: {:.2f}>'
69+
return fmt.format(self.total(), self.due())
70+
71+
72+
class Promotion(ABC): # the Strategy: an Abstract Base Class
73+
74+
@abstractmethod
75+
def discount(self, order):
76+
"""Return discount as a positive dollar amount"""
77+
78+
79+
class FidelityPromo(Promotion): # first Concrete Strategy
80+
"""5% discount for customers with 1000 or more fidelity points"""
81+
82+
def discount(self, order):
83+
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
84+
85+
86+
class BulkItemPromo(Promotion): # second Concrete Strategy
87+
"""10% discount for each LineItem with 20 or more units"""
88+
89+
def discount(self, order):
90+
discount = 0
91+
for item in order.cart:
92+
if item.quantity >= 20:
93+
discount += item.total() * .1
94+
return discount
95+
96+
97+
class LargeOrderPromo(Promotion): # third Concrete Strategy
98+
"""7% discount for orders with 10 or more distinct items"""
99+
100+
def discount(self, order):
101+
distinct_items = {item.product for item in order.cart}
102+
if len(distinct_items) >= 10:
103+
return order.total() * .07
104+
return 0
105+
106+
# END CLASSIC_STRATEGY

novatec/composite.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
r"""
2+
Exemplo do padão Composite
3+
==========================
4+
5+
Aplicação: catálogo de produtos eletrônicos para hobistas.
6+
7+
A *Folha* de um catálogo é a classe ``Componente``::
8+
9+
>>> ard = Componente(1, 'Arduino Uno', 79.95)
10+
>>> ard
11+
Componente(sku=1, nome='Arduino Uno', preco=79.95)
12+
>>> ard.preco
13+
79.95
14+
>>> bobs = Componente(2, "Bob's Duino", 59.95)
15+
>>> bobs
16+
Componente(sku=2, nome="Bob's Duino", preco=59.95)
17+
>>> str(ard)
18+
'Arduino Uno (#1)\t$79.95'
19+
>>> cabo_usb = Componente(3, 'Cabo USB azul 1m', 4.95)
20+
21+
Um catálogo é uma lista de produtos, que pode ser exibida formatada::
22+
23+
>>> cat = Catalogo([ard, bobs, cabo_usb])
24+
>>> cat
25+
<Catalogo (3 produtos)>
26+
>>> print(cat) # doctest: +NORMALIZE_WHITESPACE
27+
Arduino Uno (#1) $79.95
28+
Bob's Duino (#2) $59.95
29+
Cabo USB azul 1m (#3) $4.95
30+
31+
Um kit é um produto formato por mais de um componente.
32+
33+
>>> kit1 = Kit(4, 'Arduino completíssimo', [ard, cabo_usb])
34+
>>> kit1
35+
<Kit #4 'Arduino completíssimo' (2 produtos)>
36+
37+
Por padrão, o preço do kit é soma dos preços dos componentes incluídos.
38+
39+
>>> kit1.preco
40+
84.9
41+
42+
A apresentação do kit inclui o nome dos componentes::
43+
44+
>>> print(kit1) # doctest: +NORMALIZE_WHITESPACE
45+
Arduino completíssimo (#4) $84.90
46+
- Arduino Uno
47+
- Cabo USB azul 1m
48+
49+
Na listagem do catálogo, os componentes dos kits também aparecem::
50+
51+
>>> cat = Catalogo([kit1, ard, bobs, cabo_usb])
52+
>>> print(cat) # doctest: +NORMALIZE_WHITESPACE
53+
Arduino completíssimo (#4) $84.90
54+
- Arduino Uno
55+
- Cabo USB azul 1m
56+
Arduino Uno (#1) $79.95
57+
Bob's Duino (#2) $59.95
58+
Cabo USB azul 1m (#3) $4.95
59+
60+
"""
61+
62+
class Componente:
63+
"""Classe *Folha* (*Leaf*) no design pattern"""
64+
65+
def __init__(self, sku, nome, preco):
66+
self.sku = sku
67+
self.nome = nome
68+
self.preco = preco
69+
70+
def __repr__(self):
71+
return "Componente(sku={}, nome={!r}, preco={})".format(
72+
self.sku, self.nome, self.preco)
73+
74+
def __str__(self):
75+
return '{} (#{})\t${}'.format(self.nome, self.sku, self.preco)
76+
77+
78+
class Kit:
79+
"""Classe *Composite* no design pattern"""
80+
81+
def __init__(self, sku, nome, produtos):
82+
self.sku = sku
83+
self.nome = nome
84+
self.produtos = list(produtos)
85+
86+
def __repr__(self):
87+
return '<Kit #{} {!r} ({} produtos)>'.format(
88+
self.sku, self.nome, len(self.produtos))
89+
90+
def __str__(self):
91+
saida = ['{} (#{})\t${:0.2f}'.format(self.nome, self.sku, self.preco)]
92+
for produto in self.produtos:
93+
saida.append('- {}'.format(produto.nome))
94+
return '\n'.join(saida)
95+
96+
97+
@property
98+
def preco(self):
99+
return sum(p.preco for p in self.produtos)
100+
101+
102+
class Catalogo:
103+
"""Classe *Cliente* no design pattern"""
104+
105+
def __init__(self, produtos):
106+
self.produtos = list(produtos)
107+
108+
def __repr__(self):
109+
return '<Catalogo ({} produtos)>'.format(len(self.produtos))
110+
111+
def __str__(self):
112+
saida = []
113+
for produto in self.produtos:
114+
saida.append(str(produto))
115+
return '\n'.join(saida)

novatec/observer.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
3+
>>> p = PesquisaEleitoral()
4+
>>> p.adicionar_votos('A', 5)
5+
5 votos adicionados para 'A'
6+
>>> p.adicionar_votos('B', 3)
7+
3 votos adicionados para 'B'
8+
9+
Observadores em ação::
10+
11+
>>> p.vincular_observador(estatistica)
12+
>>> p.adicionar_votos('A', 2)
13+
2 votos adicionados para 'A'
14+
Estatística: A 70%, B 30%
15+
>>> p.vincular_observador(grafico)
16+
>>> p.adicionar_votos('B', 7)
17+
7 votos adicionados para 'B'
18+
Estatística: A 41%, B 59%
19+
A ############################
20+
B #########################################
21+
"""
22+
23+
class PesquisaEleitoral:
24+
"""Classe *Sujeito* do padrão *Observer*"""
25+
26+
def __init__(self):
27+
self.votos = {'A':0, 'B':0}
28+
self.observadores = []
29+
30+
def adicionar_votos(self, candidato, votos):
31+
print('{} votos adicionados para {!r}'.format(votos, candidato))
32+
self.votos[candidato] += votos
33+
self.notificar_observadores()
34+
35+
def vincular_observador(self, observador):
36+
self.observadores.append(observador)
37+
38+
def notificar_observadores(self):
39+
for obs in self.observadores:
40+
obs(self)
41+
42+
def estatistica(pesquisa):
43+
total = sum(pesquisa.votos.values())
44+
pct_a = pesquisa.votos['A'] / total * 100
45+
pct_b = pesquisa.votos['B'] / total * 100
46+
print('Estatística: A {:0.0f}%, B {:0.0f}%'.format(pct_a, pct_b))
47+
48+
def grafico(pesquisa):
49+
total = sum(pesquisa.votos.values())
50+
print('A', '#' * int(pesquisa.votos['A'] / total * 70))
51+
print('B', '#' * int(pesquisa.votos['B'] / total * 70))

novatec/saobernardo.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
class Barril:
3+
4+
def __init__(self, doses=10):
5+
self.doses = doses
6+
7+
def servir(self):
8+
if self.doses > 0:
9+
return '1 dose'
10+
else:
11+
raise LookupError('barril vazio')
12+
13+
def encher(self, doses):
14+
self.doses += doses
15+
16+
class SaoBernardo:
17+
18+
def __init__(self, nome):
19+
self.nome = nome
20+
self._barril = Barril()
21+
22+
def servir(self):
23+
dose = self._barril.servir()
24+
print('{} servindo: {}'.format(self.nome, dose))
25+
return dose
26+
27+
def __getattr__(self, nome):
28+
if hasattr(self._barril, nome):
29+
return getattr(self._barril, nome)
30+
else:
31+
raise AttributeError('atributo desconhecido')

novatec/singleton.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
class Singleton:
3+
4+
def __new__(cls, *args, **kwargs):
5+
if not hasattr(cls, '_a_instancia'):
6+
cls._a_instancia = super().__new__(cls, *args, **kwargs)
7+
8+
return cls._a_instancia

0 commit comments

Comments
 (0)