Apostila de Exercc3adcios de Lc3adngua Portuguesa 9 Ano Com Descritores
Encapsulamento com descritores
-
Upload
luciano-ramalho -
Category
Technology
-
view
446 -
download
1
description
Transcript of Encapsulamento com descritores
![Page 2: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/2.jpg)
Turing.com.br
Pré-requistos da palestra
• Para acompanhar os slides a seguir, é preciso saber como funciona o básico de orientação a objetos em Python. Especificamente:
• contraste entre atributos de classe e de instância
• herança de atributos de classe (métodos e campos)
• atributos protegidos: como e quando usar
• como e quando usar a função super
![Page 3: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/3.jpg)
Turing.com.br
O cenário• Comércio de alimentos a granel
• Um pedido tem vários itens
• Cada item tem descrição, peso (kg), preço unitário (p/ kg) e sub-total
![Page 4: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/4.jpg)
Turing.com.br
➊
![Page 5: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/5.jpg)
➊ o primeiro doctest=======Passo 1=======
Um pedido de alimentos a granel é uma coleção de ``ItemPedido``.Cada item possui campos para descrição, peso e preço::
! >>> from granel import ItemPedido! >>> ervilha = ItemPedido('ervilha partida', 10, 3.95)! >>> ervilha.descricao, ervilha.peso, ervilha.preco! ('ervilha partida', 10, 3.95)
Um método ``subtotal`` fornece o preço total de cada item::
! >>> ervilha.subtotal()! 39.5
![Page 6: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/6.jpg)
Turing.com.br
➊ mais simples, impossível
class ItemPedido(object):
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
o método inicializador é conhecido como “dunder init”
![Page 7: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/7.jpg)
>>> ervilha = ItemPedido('ervilha partida', .5, 7.95)>>> ervilha.descricao, ervilha.peso, ervilha.preco('ervilha partida', .5, 7.95)>>> ervilha.peso = -10>>> ervilha.subtotal()-79.5
Turing.com.br
➊ porém, simples demais
isso vai dar problema na hora de cobrar...
Jeff Bezos of Amazon: Birth of a SalesmanWSJ.com - http://j.mp/VZ5not
“Descobrimos que os clientes conseguiam encomendar uma quantidade negativa de livros! E nós creditávamos o valor em seus cartões...” Jeff Bezos
![Page 8: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/8.jpg)
➊ a solução clássicaclass ItemPedido(object):
def __init__(self, descricao, peso, preco): self.descricao = descricao self.set_peso(peso) self.preco = preco
def subtotal(self): return self.get_peso() * self.preco
def get_peso(self): return self.__peso
def set_peso(self, valor): if valor > 0: self.__peso = valor else: raise ValueError('valor deve ser > 0')
atributoprotegido
mudançasna interface
![Page 9: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/9.jpg)
• Antes podíamos acessar o peso de um item escrevendo apenas item.peso, mas agora não...
• Isso quebra código das classes clientes
• Python oferece outro caminho...
➊ porém, a API foi alterada!>>> ervilha.pesoTraceback (most recent call last): ...AttributeError: 'ItemPedido' object has no attribute 'peso'
![Page 10: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/10.jpg)
➊ atributos protegidos
• Atributos protegidos em Python são salvaguardas
• servem para evitar atribuição ou sobrescrita acidental
• não para evitar usos (ou abusos) intencionais
![Page 11: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/11.jpg)
>>> ervilha._ItemPedido__peso10
• Atributos protegidos em Python são salvaguardas
• servem para evitar atribuição ou sobrescrita acidental
• não para evitar usos (ou abusos) intencionais
➊ atributos protegidos
![Page 12: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/12.jpg)
Turing.com.br
➋
![Page 13: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/13.jpg)
O peso de um ``ItemPedido`` deve ser maior que zero::
! >>> ervilha.peso = 0! Traceback (most recent call last):! ! ...! ValueError: valor deve ser > 0! >>> ervilha.peso! 10
➋ o segundo doctest
parece uma violação de encapsulamento
mas a lógica do negócio é preservada
peso não foi alterado
![Page 14: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/14.jpg)
Turing.com.br
➋ validação com property
peso agora é uma property
O peso de um ``ItemPedido`` deve ser maior que zero::
! >>> ervilha.peso = 0! Traceback (most recent call last):! ! ...! ValueError: valor deve ser > 0! >>> ervilha.peso! 10
![Page 15: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/15.jpg)
Turing.com.br
➋ implementar propertyclass ItemPedido(object):
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
@property def peso(self): return self.__peso
@peso.setter def peso(self, valor): if valor > 0: self.__peso = valor else: raise ValueError('valor deve ser > 0')
atributo protegido
![Page 16: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/16.jpg)
Turing.com.br
➋ implementar propertyclass ItemPedido(object):
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
@property def peso(self): return self.__peso
@peso.setter def peso(self, valor): if valor > 0: self.__peso = valor else: raise ValueError('valor deve ser > 0')
no __init__ a property já está em uso
![Page 17: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/17.jpg)
Turing.com.br
➋ implementar propertyclass ItemPedido(object):
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
@property def peso(self): return self.__peso
@peso.setter def peso(self, valor): if valor > 0: self.__peso = valor else: raise ValueError('valor deve ser > 0')
o atributo protegido __peso só é acessado nos métodos da property
![Page 18: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/18.jpg)
Turing.com.br
class ItemPedido(object):
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
@property def peso(self): return self.__peso
@peso.setter def peso(self, valor): if valor > 0: self.__peso = valor else: raise ValueError('valor deve ser > 0')
➋ implementar property
e se quisermos a mesma lógicapara o preco?
teremos que duplicar tudo isso?
![Page 19: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/19.jpg)
Turing.com.br
➌
![Page 20: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/20.jpg)
➌ os atributos gerenciados (managed attributes)
usaremos descritores para gerenciar o acesso aos atributos peso e preco, preservando a lógica de negócio__init__
subtotal
descricaopeso {descriptor}preco {descriptor}
ItemPedido
![Page 21: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/21.jpg)
Turing.com.br
➌ validação com descriptor
peso e preco são atributos da classe ItemPedido
a lógica fica em __get__ e __set__, podendo ser reutilizada
![Page 22: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/22.jpg)
➌
implementaçãodo descritor
class Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
class ItemPedido(object): peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
classenew-style
![Page 23: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/23.jpg)
Turing.com.br
➊ a classe produz instâncias
classeinstâncias
![Page 24: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/24.jpg)
Turing.com.br
➌ a classe descriptor
classe
instâncias
![Page 25: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/25.jpg)
Turing.com.br
➌ uso do descriptor
a classe ItemPedidotem duas instâncias de Quantidade associadas a ela
![Page 26: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/26.jpg)
class Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
class ItemPedido(object): peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
Turing.com.br
➌
implementaçãodo descriptor
![Page 27: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/27.jpg)
class ItemPedido(object): peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
Turing.com.br
➌ uso do descriptor
a classe ItemPedidotem duas instâncias de Quantidade associadas a ela
![Page 28: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/28.jpg)
Turing.com.br
➌ uso do descriptor
class ItemPedido(object): peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
cada instância da classe Quantidade controla um atributo de ItemPedido
![Page 29: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/29.jpg)
➌ uso do descriptor
class ItemPedido(object): peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
todos os acessos a peso e precopassam pelos descritores
![Page 30: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/30.jpg)
Turing.com.br
➌ implementar o descriptorclass Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
uma classe com método __get__ é um descriptor
![Page 31: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/31.jpg)
class Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
Turing.com.br
➌ implementar o descriptor
self é a instância do descritor (associadaao preco ou ao peso)
![Page 32: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/32.jpg)
class Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
Turing.com.br
➌ implementar o descriptor
self é a instância do descritor (associadaao preco ou ao peso)
instance é a instância de ItemPedido que está sendo acessada
![Page 33: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/33.jpg)
class Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
Turing.com.br
➌ implementar o descriptornome_alvo é o nome do atributo da instância de ItemPedido que este descritor (self) controla
![Page 34: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/34.jpg)
Turing.com.br
➌ implementar o descriptor
__get__ e __set__ manipulam o atributo-alvo no objeto ItemPedido
![Page 35: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/35.jpg)
class Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
Turing.com.br
➌ implementar o descriptor
__get__ e __set__ usam getattr e setattr para manipular o atributo-alvo na instância de ItemPedido
![Page 36: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/36.jpg)
➌ descriptor implementation
cada instância de descritor gerencia um atributo específico das instâncias de ItemPedido e precisa de um nome_alvo específico
![Page 37: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/37.jpg)
Turing.com.br
➌ inicialização do descritor
class ItemPedido(object): peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
quando um descritor é instanciado, o atributo ao qual ele será vinculado ainda não existe!
exemplo: o atributo preco só passa a existir após a atribuição
![Page 38: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/38.jpg)
class Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
Turing.com.br
➌ implementar o descriptor
temos que gerar um nome para o atributo-alvo onde será armazenado o valor na instância de ItemPedido
![Page 39: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/39.jpg)
class Quantidade(object): __contador = 0
def __init__(self): prefixo = self.__class__.__name__ chave = self.__class__.__contador self.nome_alvo = '%s_%s' % (prefixo, chave) self.__class__.__contador += 1
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
cada instância de Quantidade precisa criar e usar um nome_alvo diferente
➌ implementar o descriptor
![Page 40: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/40.jpg)
Turing.com.br
➌ implementar o descriptor
>>> ervilha = ItemPedido('ervilha partida', .5, 3.95)>>> ervilha.descricao, ervilha.peso, ervilha.preco('ervilha partida', .5, 3.95)>>> dir(ervilha)['Quantidade_0', 'Quantidade_1', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'descricao', 'peso', 'preco', 'subtotal']
Quantidade_0 e Quantidade_1 são os atributos-alvo
![Page 41: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/41.jpg)
➌ os atributos alvo
Quantidade_0 armazena o valor de peso
__init____get____set__
nome_alvo
«descriptor»Quantidade
__init__subtotal
descricaoQuantidade_0Quantidade_1
ItemPedido«peso»
«preco»
«get/set atributo alvo»
Quantidade_1 armazena o valor de preco
![Page 42: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/42.jpg)
➌ os atributos gerenciados
clientes da classe ItemPedido não precisam saber como peso e preco são gerenciados
E nem precisam saber que Quantidade_0 e Quantidade_1 existem!
__init__subtotal
descricaopeso {descriptor}preco {descriptor}
ItemPedido
![Page 43: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/43.jpg)
➌ próximos passos
• Seria melhor se os atributos-alvo fossem atributos protegidos
• _ItemPedido__peso em vez de _Quantitade_0
• Para fazer isso, precisamos descobrir o nome do atributo gerenciado (ex. peso)
• isso não é tão simples quanto parece
• pode ser que não valha a pena complicar mais
![Page 44: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/44.jpg)
class ItemPedido(object): peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
➌ o desafio quando cada descritor é instanciado, a classe ItemPedido não existe, e nem os atributos gerenciados
![Page 45: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/45.jpg)
class ItemPedido(object): peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
def subtotal(self): return self.peso * self.preco
➌ o desafiopor exemplo, o atributo peso só é criado depois que Quantidade() é instanciada
![Page 46: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/46.jpg)
Próximos passos• Se o descritor precisar saber o nome do atributo
gerenciado
(talvez para salvar o valor em um banco de dados, usando nomes de colunas descritivos, como faz o Django)
• ...então você vai precisar controlara construção da classe gerenciadacom uma...
![Page 47: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/47.jpg)
Turing.com.br
Acelerando...
![Page 48: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/48.jpg)
Turing.com.br
➏
![Page 49: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/49.jpg)
Turing.com.br
➎ metaclasses criam classes!metaclasses são
classes cujas instâncias são
classes
![Page 50: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/50.jpg)
Turing.com.br
➏ simplicidade aparente
![Page 51: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/51.jpg)
Turing.com.br
from modelo import Modelo, Quantidade
class ItemPedido(Modelo):
peso = Quantidade() preco = Quantidade()
def __init__(self, descricao, peso, preco): self.descricao = descricao self.peso = peso self.preco = preco
➏ o poder da abstração
![Page 52: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/52.jpg)
Turing.com.br
class Quantidade(object):
def __init__(self): self.set_nome(self.__class__.__name__, id(self))
def set_nome(self, prefix, key): self.nome_alvo = '%s_%s' % (prefix, key)
def __get__(self, instance, owner): return getattr(instance, self.nome_alvo)
def __set__(self, instance, value): if value > 0: setattr(instance, self.nome_alvo, value) else: raise ValueError('valor deve ser > 0')
class ModeloMeta(type):
def __init__(cls, nome, bases, dic): super(ModeloMeta, cls).__init__(nome, bases, dic) for chave, atr in dic.items(): if hasattr(atr, 'set_nome'): atr.set_nome('__' + nome, chave)
class Modelo(object): __metaclass__ = ModeloMeta
➏ módulo modelo.py
![Page 53: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/53.jpg)
Turing.com.br
➏ esquema final +
![Page 54: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/54.jpg)
Referências
• Raymond Hettinger’s Descriptor HowTo Guide (part of the official Python docs.)
• Alex Martelli’sPython in a Nutshell, 2e. (Python 2.5 but still excellent, includes the complete attribute access algorithm)
![Page 55: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/55.jpg)
Referências
• David Beazley’sPython Essential Reference, 4th edition(covers Python 2.6)
• Source code and doctests for this talk:http://github.com/ramalho/talks/tree/master/encap(will move to: https://github.com/oturing/encapy)
![Page 56: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/56.jpg)
A revelação final
• Funções em Python são descritores!
• implementam __get__
• É assim que uma função, quando acessada como atributo de uma instância se torna um bound method (método vinculado)
• fn.__get__ devolve uma aplicação parcial de fn, vinculando self à instância-alvo
Elegante, hein?
![Page 57: Encapsulamento com descritores](https://reader030.fdocuments.net/reader030/viewer/2022020110/549653e1b47959564d8b4f75/html5/thumbnails/57.jpg)
Turing.com.br
Oficinas Turing:computação para programadores
• Próximos lançamentos:
• 1ª turma de Python para quem usa Django
• 3ª turma de Objetos Pythonicos
• 4ª turma de Python para quem sabe Python
Para saber mais sobre estes cursos ONLINE escreva para: