O documento descreve as etapas de desenvolvimento de uma classe em Python para representar itens de pedidos, com o objetivo de controlar o acesso aos atributos das instâncias de forma a garantir a integridade dos dados. Inicialmente é implementada uma classe simples, porém com acesso irrestrito aos atributos (➊). Posteriormente são acrescentadas propriedades para validar os valores atribuídos (➋) e descritores de classe para reutilizar a lógica de validação (➌). Por fim, são definidos nomes descritivos para
Python não força o programador a pensar em objetos, mas eles fazem parte da linguagem desde o início, incluindo conceitos avançados como sobrecarga de operadores, herança múltipla e introspecção. Com sua sintaxe simples, é muito natural aprender orientação a objetos em Python
Python não força o programador a pensar em objetos, mas eles fazem parte da linguagem desde o início, incluindo conceitos avançados como sobrecarga de operadores, herança múltipla e introspecção. Com sua sintaxe simples, é muito natural aprender orientação a objetos em Python
Slides da disciplina de Análise de Algoritmos, ministrada pelo Prof. Marcelo H. Carvalho no curso de Pós-Graduação em Ciência da Computação, FACOM - UFMS.
Slide completo sobre a Linguagem de Programação Lua.
Conteúdo:
- Definição.
- Mercado.
- Quem a utiliza.
- Características.
- Sintaxe da Linguagem.
- Códigos de Exemplos.
Apresentando a Linguagem de Programação PythonPriscila Mayumi
Slides para apresentação da linguagem Python. Trabalho para a matéria "Novas Tecnologias" na Universidade Metodista de São Paulo. Lembrando que eu tive que estudar muito sobre, pois nunca tive um contato "suficiente" com Python.
This presentation educates you about objectives of python with example syntax, OOP Terminology, Creating Classes, Creating Instance Objects, Accessing Attributes and Built-In Class Attributes.
My Beginners Perl tutorial, much abbreviated and as presented at the London Perl Workshop on Dec 1st 2007.
Also includes the section on Regular Expressions that we didn't have time for on the day.
https://pandas.pydata.org/
Biblioteca open source,
Licenciado sobre BSD
Alto desempenho
Fácil de utilizar
Inclui ferramentas de estruturas de dados e análise de dados
Palestra sobre meta-programação em python ministrada no TDC 2012 e na SEMCOMP 2012. Corrigido o verbo "estender" que estava antes "extender" e colocado realce de sintaxe.
Slides da disciplina de Análise de Algoritmos, ministrada pelo Prof. Marcelo H. Carvalho no curso de Pós-Graduação em Ciência da Computação, FACOM - UFMS.
Slide completo sobre a Linguagem de Programação Lua.
Conteúdo:
- Definição.
- Mercado.
- Quem a utiliza.
- Características.
- Sintaxe da Linguagem.
- Códigos de Exemplos.
Apresentando a Linguagem de Programação PythonPriscila Mayumi
Slides para apresentação da linguagem Python. Trabalho para a matéria "Novas Tecnologias" na Universidade Metodista de São Paulo. Lembrando que eu tive que estudar muito sobre, pois nunca tive um contato "suficiente" com Python.
This presentation educates you about objectives of python with example syntax, OOP Terminology, Creating Classes, Creating Instance Objects, Accessing Attributes and Built-In Class Attributes.
My Beginners Perl tutorial, much abbreviated and as presented at the London Perl Workshop on Dec 1st 2007.
Also includes the section on Regular Expressions that we didn't have time for on the day.
https://pandas.pydata.org/
Biblioteca open source,
Licenciado sobre BSD
Alto desempenho
Fácil de utilizar
Inclui ferramentas de estruturas de dados e análise de dados
Palestra sobre meta-programação em python ministrada no TDC 2012 e na SEMCOMP 2012. Corrigido o verbo "estender" que estava antes "extender" e colocado realce de sintaxe.
Esta apostila foi criada pelo autor apresentando os principais conceitos de Orientação a objetos dentro da linguagem Python. Nela o leitor encontrará conceitos e exemplos em Python com explicações detalhadas . O leitor encontra conteúdo sobre: como criar e implementar uma classes , métodos. herança, abstração, polimorfismo e outros temas da orientação a objetos.
Aqui são apresentados conceitos básicos a plataforma Java. Simples e rápido.
/**Depois que entrei no mundo Java, começei a procurar por conteúdo na internet para estudar, então me deparei com um ótimo site, http://www.argonavis.com.br, de um grande cara chamado Helder Rocha, que disponibiliza este mesmo conteúdo em seu site também. Obrigado pela ajuda a comunidade.*/
Essa apresentação fala um pouco sobre o que é, quando e porque aplicar Refatoração em seu código.
Além de mostrar algumas técnicas que Martin Fowler mostra em seu livro.
Se você não usa geradores, está deixando de aproveitar um recurso poderoso de Python. Partimos do pattern Iterator e mostramos seus usos práticos e suporte nativo na linguagem, incluindo funções e expressões geradoras, que permitem lidar com massas de dados muito grandes de modo eficiente e com baixo consumo de memória. Ao final, mostramos o uso prático de funções geradoras em uma ferramenta de conversão de bancos de dados.
Alex Martelli's 45' talk about Design Patterns translated to Brazilian Portuguese under permission from the author.
PT-BR:
A palestra de 45 min sobre Padrões de Projeto do Alex Martelli traduzida para o português do Brasil, com a permissão do autor.
3. 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
Turing.com.br
4. Roteiro da palestra
• A partir de um cenário inicial, implementamos uma
classe muito simples
• A partir daí, evoluímos a implementação em seis
etapas para controlar o acesso aos campos das
instâncias, usando propriedades, descritores e
finalmente uma metaclasse
• Nos slides, as etapas são identificadas por
números: ➊, ➋, ➌...
Turing.com.br
5. 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
Turing.com.br
7. ➊ a classe produz instâncias
classe
instâncias
Turing.com.br
8. ➊ mais simples, impossível
o método
inicializador é
conhecido como
class ItemPedido(object): “dunder init”
def __init__(self, descricao, peso, preco):
self.descricao = descricao
self.peso = peso
self.preco = preco
def subtotal(self):
Turing.com.br self.peso * self.preco
return
9. ➊ porém, simples demais
>>> ervilha = ItemPedido('ervilha partida', .5, 7.95)
>>> ervilha.descricao, ervilha.peso, ervilha.preco
('ervilha partida', .5, 7.95)
>>> ervilha.peso = -10
>>> ervilha.subtotal()
isso vai dar
-79.5 problema na
hora de cobrar...
Turing.com.br
10. ➊ porém, simples demais
>>> ervilha = ItemPedido('ervilha partida', .5, 7.95)
>>> ervilha.descricao, ervilha.peso, ervilha.preco
('ervilha partida', .5, 7.95)
>>> ervilha.peso = -10
>>> ervilha.subtotal()
isso vai dar
-79.5 problema na
hora de cobrar...
“We found that customers could
order a negative quantity of books!
And we would credit their credit
card with the price...” Jeff Bezos
Jeff Bezos of Amazon: Birth of a Salesman
Turing.com.br WSJ.com - http://j.mp/VZ5not
11. ➊ porém, simples demais
>>> ervilha = ItemPedido('ervilha partida', .5, 7.95)
>>> ervilha.descricao, ervilha.peso, ervilha.preco
('ervilha partida', .5, 7.95)
>>> ervilha.peso = -10
>>> ervilha.subtotal()
isso vai dar
-79.5 problema na
hora de cobrar...
“Descobrimos que os clientes
conseguiam encomendar uma
quantidade negativa de livros!
E nós creditávamos o valor em
seus cartões...” Jeff Bezos
Jeff Bezos of Amazon: Birth of a Salesman
Turing.com.br WSJ.com - http://j.mp/VZ5not
12. ➋ validação com property
>>> ervilha = ItemPedido('ervilha partida', .5, 7.95)
>>> ervilha.descricao, ervilha.peso, ervilha.preco
('ervilha partida', .5, 7.95)
>>> ervilha.peso = -10 parece uma
Traceback (most recent call last):
... violação de
ValueError: valor deve ser > 0 encapsulamento
mas a lógica do negócio
está preservada:
peso agora é uma property
Turing.com.br
13. ➋ implementar property
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')
Turing.com.br
14. ➋ implementar property
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): atributo
return self.__peso
protegido
@peso.setter
def peso(self, valor):
if valor > 0:
self.__peso = valor
else:
raise ValueError('valor deve ser > 0')
Turing.com.br
15. ➋ implementar property
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
no __init__ a
property já
@property
def peso(self): está em uso
return self.__peso
@peso.setter
def peso(self, valor):
if valor > 0:
self.__peso = valor
else:
raise ValueError('valor deve ser > 0')
Turing.com.br
16. ➋ implementar property
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 atributo
@property protegido
def peso(self): __peso só é
return self.__peso
acessado nos
@peso.setter métodos da
def peso(self, valor):
if valor > 0: property
self.__peso = valor
else:
raise ValueError('valor deve ser > 0')
Turing.com.br
17. ➋ implementar property
class ItemPedido(object):
def __init__(self, descricao, peso, preco):
self.descricao = descricao
self.peso = peso
self.preco = preco ese quisermos
def subtotal(self):
a mesma lógica
return self.peso * self.preco para o preco?
@property
def peso(self):
return self.__peso
teremos que
@peso.setter duplicar tudo
def peso(self, valor):
if valor > 0:
isso?
self.__peso = valor
else:
raise ValueError('valor deve ser > 0')
Turing.com.br
18. ➌ validação com descriptor
peso e preco
são atributos
da classe a lógica fica em
ItemPedido __get__ e __set__,
podendo ser reutilizada
Turing.com.br
21. ➌ uso do descriptor
a classe
ItemPedido
tem duas
instâncias de
Quantidade
associadas a ela
Turing.com.br
22. ➌ uso do descriptor
a classe
class ItemPedido(object):
peso = Quantidade()
ItemPedido
preco = Quantidade() tem duas
def __init__(self, descricao, peso, preco):
instâncias de
self.descricao = descricao Quantidade
self.peso = peso
self.preco = preco
associadas a ela
def subtotal(self):
return self.peso * self.preco
Turing.com.br
23. ➌ uso do descriptor
class ItemPedido(object):
peso = Quantidade() cada instância
preco = Quantidade()
da classe
def __init__(self, descricao, peso, preco): Quantidade
self.descricao = descricao
self.peso = peso controla um
self.preco = preco atributo de
def subtotal(self): ItemPedido
return self.peso * self.preco
Turing.com.br
24. ➌ implementar o descriptor
class Quantidade(object):
def __init__(self):
prefixo = self.__class__.__name__
chave = id(self)
self.nome_alvo = '%s_%s' % (prefixo, chave)
def __get__(self, instance, owner):
return getattr(instance, self.nome_alvo)
uma classe
def __set__(self, instance, value):
if value > 0:
com método
setattr(instance, self.nome_alvo, value) __get__ é um
else:
raise ValueError('valor deve ser > 0') descriptor
Turing.com.br
25. ➌ implementar o descriptor
class Quantidade(object):
def __init__(self):
prefixo = self.__class__.__name__
chave = id(self)
self.nome_alvo = '%s_%s' % (prefixo, chave)
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')
self é a instância
do descritor (associada
Turing.com.br ao preco ou ao peso)
26. ➌ implementar o descriptor
class Quantidade(object):
def __init__(self):
prefixo = self.__class__.__name__
chave = id(self)
self.nome_alvo = '%s_%s' % (prefixo, chave)
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: instance é a instância
de ItemPedido que está
raise ValueError('valor deve ser > 0')
self é a instância sendo acessada
do descritor (associada
Turing.com.br ao preco ou ao peso)
27. ➌ implementar o descriptor
class Quantidade(object): nome_alvo é
def __init__(self):
o nome do
prefixo = self.__class__.__name__ atributo da
chave = id(self)
self.nome_alvo = '%s_%s' % (prefixo, chave) instância de
def __get__(self, instance, owner):
ItemPedido
return getattr(instance, self.nome_alvo) que este
def __set__(self, instance, value): descritor
if value > 0:
setattr(instance, self.nome_alvo, value)
(self)
else: controla
raise ValueError('valor deve ser > 0')
Turing.com.br
28. ➌ implementar o descriptor
__get__ e __set__
manipulam o atributo-alvo
Turing.com.br no objeto ItemPedido
29. ➌ implementar o descriptor
class Quantidade(object):
def __init__(self):
prefixo = self.__class__.__name__
chave = id(self)
self.nome_alvo = '%s_%s' % (prefixo, chave)
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')
__get__ e __set__ usam
getattr e setattr para manipular o
Turing.com.br atributo-alvo na instância de ItemPedido
30. ➌ inicialização do descritor
quando um descritor é
instanciado, o atributo ao
class ItemPedido(object): qual ele será vinculado
peso = Quantidade()
preco = Quantidade() ainda não existe!
def __init__(self, descricao, peso, preco):
self.descricao = descricao
self.peso = peso
self.preco = preco
def subtotal(self): exemplo: o
return self.peso * self.preco
atributo preco
só passa a
existir após a
atribuição
Turing.com.br
31. ➌ implementar o descriptor
class Quantidade(object):
def __init__(self):
prefixo = self.__class__.__name__
chave = id(self)
self.nome_alvo = '%s_%s' % (prefixo, chave)
def __get__(self, instance, owner):
return getattr(instance, self.nome_alvo)
def __set__(self, instance, value):
if value > 0:
temos que inventar um
setattr(instance, self.nome_alvo, value)
else:
nome para o atributo-alvo
raise ValueError('valor deve ser > 0')
onde será armazenado o
valor na instância de
ItemPedido
Turing.com.br
32. ➌ implementar o descriptor
>>> ervilha = ItemPedido('ervilha partida', .5, 3.95)
>>> ervilha.descricao, ervilha.peso, ervilha.preco
('ervilha partida', .5, 3.95)
>>> dir(ervilha)
['Quantidade_4299545872', 'Quantidade_4299546064',
'__class__', '__delattr__', '__dict__', '__doc__',
'__format__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'descricao', 'peso', 'preco',
'subtotal']
nesta implementação, os nomes dos
atributos-alvo não são descritivos,
Turing.com.br
dificultando a depuração
33. ➍ usar nomes descritivos
ItemPedido.__new__ invoca
«quantidade».set_nome
Turing.com.br para redefinir o nome_alvo
34. ➍ usar nomes descritivos
ItemPedido.__new__ invoca «quantidade».set_nome
«quantidade».set_nome
Turing.com.br redefine o nome_alvo
36. ➍ usar nomes descritivos
«quantidade».set_nome
class Quantidade(object):
redefine o nome_alvo
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')
Turing.com.br
37. ➍ usar nomes descritivos
class ItemPedido(object):
peso = Quantidade()
preco = Quantidade()
def __new__(cls, *args, **kwargs):
for chave, atr in cls.__dict__.items():
if hasattr(atr, 'set_nome'):
atr.set_nome('__' + cls.__name__, chave)
return super(ItemPedido, cls).__new__(cls, *args, **kwargs)
def __init__(self, descricao, peso, preco):
self.descricao = descricao
self.peso = peso
self.preco = preco Quando __init__
def subtotal(self): executa, o descritor
return self.peso * self.preco
já está configurado
com um nome de
atributo-alvo
Turing.com.br
descritivo
38. ➍ usar nomes descritivos
ItemPedido.__new__ invoca «quantidade».set_nome
Turing.com.br
39. ➍ usar nomes descritivos
«quantidade».set_nome
Turing.com.br redefine o nome_alvo
40. ➍ nomes descritivos
>>> ervilha = ItemPedido('ervilha partida', .5, 3.95)
>>> ervilha.descricao, ervilha.peso, ervilha.preco
('ervilha partida', 0.5, 3.95)
>>> dir(ervilha)
['__ItemPedido_peso', '__ItemPedido_preco',
'__class__', '__delattr__', '__dict__', '__doc__',
'__format__', '__getattribute__', '__hash__',
'__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'descricao', 'peso', 'preco',
'subtotal']
nesta implementação e nas
próximas, os nomes dos atributos-
alvo seguem a convenção de
Turing.com.br atributos protegidos de Python
41. ➍ funciona, mas custa caro
• ItemPedido aciona __new__
para construir cada nova
instância
• Porém a associação dos
descritores é com a classe
ItemPedido: o nome do
atributo-alvo nunca vai mudar,
uma vez definido corretamente
Turing.com.br
42. ➍ funciona, mas custa caro
• Isso significa que para cada
nova instância de
ItemPedido que é criada,
«quantidade».set_nome
é invocado duas vezes
• Mas o nome do atributo-alvo
não tem porque mudar na vida
de uma «quantidade»
Turing.com.br
43. ➍ funciona, mas custa caro
1500000.0 1427386
7.3 ×
1125000.0
980708
750000.0
585394
375000.0
80004
0
versão 1 versão 2 versão 3 versão 4
Número de instâncias de ItemPedido criadas
por segundo (MacBook Pro 2011, Intel Core i7)
Turing.com.br
44. ➎ como evitar trabalho inútil
• ItemPedido.__new__ resolveu
mas de modo ineficiente.
• Cada «quantidade» deve receber
o nome do seu atributo-alvo apenas
uma vez, quando a própria classe
ItemPedido for criada
• Para isso precisamos de uma...
Turing.com.br
45. ➎ metaclasses criam classes!
metaclasses são
classes cujas
instâncias são
classes
Turing.com.br
46. ➎ metaclasses criam classes!
metaclasses são
classes cujas
instâncias são
classes
ItemPedido é uma
instância de type
type é a metaclasse default
em Python: a classe que
normalmente constroi
Turing.com.br outras classes
48. ➎ nossa metaclasse
ModeloMeta é a
metaclasse que vai
construir a classe
ItemPedido
ModeloMeta.__init__
fará apenas uma vez o
que antes era feito em
ItemPedido.__new__
Turing.com.br a cada nova instância
49. ➎ nossa metaclasse
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)
Assim dizemos que a
class ItemPedido(object):
__metaclass__ = ModeloMeta classe ItemPedido herda
peso = Quantidade() de object, mas é uma
preco = Quantidade()
instância (construida por)
def __init__(self, descricao, peso, preco):
self.descricao = descricao ModeloMeta
self.peso = peso
self.preco = preco
def subtotal(self):
return self.peso * self.preco
Turing.com.br
50. ➎ nossa metaclasse
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)
Este __init__ invoca
class ItemPedido(object):
__metaclass__ = ModeloMeta «quantidade».set_nome,
peso = Quantidade()
para cada descritor, uma
preco = Quantidade()
vez só, na inicialização da
def __init__(self, descricao, peso, preco):
self.descricao = descricao
classe ItemPedido
self.peso = peso
self.preco = preco
def subtotal(self):
return self.peso * self.preco
Turing.com.br
54. ➎ desempenho melhor
1500000.0 1427386
mesmo desempenho,
+ nomes amigáveis
1125000.0
980708
750000.0
585394 585771
375000.0
80004
0
versão 1 versão 2 versão 3 versão 4 versão 5
Número de instâncias de ItemPedido criadas
por segundo (MacBook Pro 2011, Intel Core i7)
Turing.com.br
60. Oficinas Turing:
computação para programadores
• Próximos lançamentos:
• 4ª turma de Python para quem sabe Python
• 3ª turma de Objetos Pythonicos
• 1ª turma de Aprenda Python com um Pythonista
Turing.com.br