'naipe']) class Baralho: valores = [str(n) for n in range(2,11)] + list('JQKA') naipes = 'paus ouros copas espadas'.split() def __init__(self): self.cartas = [Carta(v, n) for n in self.naipes for v in self.valores] def __len__(self): return len(self.cartas) def __getitem__(self, posicao): return self.cartas[posicao] 11 linhas! note: Baralho herda de object
convenção, e não formalmente veri!cada pelo compilador • Pode ser implementada parcialmente • Em Python, o protocolo de sequência tem apenas dois métodos: • s.__getitem__(chave) 㲗 s[chave] • s.__len__() 㲗 len(s)
emulates any built-in type, it is important that the emulation only be implemented to the degree that it makes sense for the object being modelled. For example, some sequences may work well with retrieval of individual elements, but extracting a slice may not make sense.
que emula qualquer tipo embutido (built-in), é importante que a emulação seja feita apenas na medida em que faz sentido para o objeto que está sendo modelado. Por exemplo, algumas sequências podem funcionar bem com a recuperação de elementos individuais, mas extrair uma fatia pode não fazer sentido.
não temos • Protocolos: de!nidos pela documentação, não declarados e muito menos veri!cados • Duck typing: o que interessa é o comportamento, não o DNA do bicho • ABC: Abstract Base Classes • Permitem especi!car interfaces e declarar classes que as implementam
'naipe']) class Baralho2(collections.abc.Sequence): valores = [str(n) for n in range(2,11)] + list('JQKA') naipes = 'paus ouros copas espadas'.split() def __init__(self): self.cartas = [Carta(v, n) for n in self.naipes for v in self.valores] def __len__(self): return len(self.cartas) def __getitem__(self, posicao): return self.cartas[posicao] collections.abc.Sequence
instâncias de classes concretas (que implementam todos os métodos abstratos) >>> baralho = BaralhoX() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Can't instantiate abstract class BaralhoX with abstract methods __len__
abstrata, Python não veri!ca se a sua classe derivada implementa todos os métodos abstratos, pois sua classe pode ser abstrata também • Por isso a veri!cação é feita somente no momento da instanciação
com um baralho... >>> shuffle(b) Traceback (most recent call last): File "<stdin>", line 1, in <module> File ".../python3.3/random.py", line 265, in shuffle x[i], x[j] = x[j], x[i] TypeError: 'Baralho' object does not support item assignment >>> ‘Baralho’ não suporta atribuição a item
os protocolos fundamentais da linguagem, com suporte sintático • mecanismos básicos: iteração, inicialização de objetos, acesso a atributos, formatação, invocação, hash, contextos (with) • operadores aritméticos e lógicos • tipos numéricos, emulação de coleções
chama os métodos especiais, e sim o interpretador Python • Quase sempre a chamada é implícita • ex: laço for i in x → iter(x) → x.__iter__() • Se precisar usar estes serviços, evite invocar diretamente o método especial • Use iter(x) em vez de x.__iter__()
• Se x.__mul__ não existe ou retorna o valor especial NotImplemented: • O interpretador invoca y.__rmul__(x) • Se y.__rmul__ não existe ou retorna o valor NotImplemented, o interpretador levanta a exceção TypeError Esse padrão chama-se double-dispatch. Fonte: http://bit.ly/st-double-dispatch
b 㲗 a = a + b • Portanto um novo objeto (a+b) é criado • Para tipos mutáveis, a implementação de métodos como __iadd__ permite a modi!cação do objeto alvo da atribuição += -= *= /= //= **= %= &= ^= |= <<= >>=
que implementam __enter__ e __exit__ with open('exemplo.txt', encoding='utf-8') as arq: for linha in arq: linha = linha.rstrip() if linha: print(linha) o objeto-arquivo devolvido por open é o gerenciador de contexto
do bloco, devolve um objeto que é atribuído à variável alvo do with/as with open('exemplo.txt', encoding='utf-8') as arq: for linha in arq: linha = linha.rstrip() if linha: print(linha) o __enter__ de file devolve self
invocado no !m do bloco, recebe informações sobre exceções ou None, None, None; se devolver True, suprime a exceção levantada with open('exemplo.txt', encoding='utf-8') as arq: for linha in arq: linha = linha.rstrip() if linha: print(linha) o __exit__ de file invoca self.close()
possui atributo a: • obj.a 㲗 obj.__getattr__(‘a’) • Acionados sempre: • bj.a = x 㲗 obj.__setattr__(‘a’, x) • del obj.a 㲗 obj.__delattr__(‘a’) o mais útil e mais fácil de implementar
㲗 obj.__getattribute__(‘a’) • Para de!nição de descritores: • __get__ • __set__ • __delete__ poderoso e difícil de implementar corretamente não temos tempo mas...
Python para quem estudou Java • 5ª turma de Objetos Pythonicos • 6ª turma de Python para quem sabe Python Para saber mais sobre estes cursos ONLINE ao VIVO visite: http://python.pro.br siga: @pythonprobr