Aula 16 – Python – Orientação a Objetos 02
Programação orientada a objetos – continuação
Que fazer esse curso com certificação?
Acesse:
https://workover.com.br/python-codigo-fluente
Voltar para página principal do blog
Todas as aulas desse curso
Aula 15 Aula 17
Antes de continuar, quero deixar meu link de afiliados na Hostinger: Hostinger
Dêem um joinha 👍 na página do Código Fluente no Facebook
Facebook
Esse é meu link de referidos na digitalocean .
Quem se cadastrar por ele, ganha $100.00 dólares de crédito na digitalocean:
Digital Ocean
Esse outro é da one.com:
One.com
Automatize tarefas do dia a dia com python:
Continuando de onde paramos na última aula.
A gente viu que podemos criar parâmetros novos em objetos em tempo de execução, o que em Java, por exemplo, não é possível.
Para criar a classe Point em java, seria mais ou menos isso:
public class Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
@Override
public String toString() {
return ("(" + x + "," + y + ")");
}
}
Se em tempo de execução você quiser inserir um parâmetro z a classe Point, não será possível, você será informado que o parâmetro não existe: Parameter z does not exist…
Voltando ao python
As classes podem ser definidas em qualquer lugar
def format_string(string, formatter=None):
'''Formata uma string usando o objeto formatador, que deve ter um
método format () que aceita uma string.'''
class DefaultFormatter:
'''Formata uma string em case title.'''
def format(self, string):
return str(string).title()
if not formatter:
formatter = DefaultFormatter()
return formatter.format(string)
Nesse caso definimos a classe DefaultFormatter dentro do método format_string.
A função format_string aceita uma string e um objeto formatador opcional, e em seguida, aplica o formatador a string.
Se nenhum formatador for fornecido, ele usará o formatador default:
Case title() coloca todas as iniciais de palavras em maiúsculo.
hello_string = "Olá, tudo bem?"
print(" input: " + hello_string)
print("output: " + format_string(hello_string))
Saída:
input: Olá, tudo bem?
output: Olá, Tudo Bem?
Quem pode acessar meus dados?
Nomes começados e terminados com 2 sublinhados( __*__ )
Nomes que começam com 2 sublinhados são métodos ou variáveis privadas da classe.
Não crie variáveis, funções, métodos, classes, enfim, não crie nada que comece e termine com 2 sublinhados.
A documentação diz que isso causa problemas de compatibilidade, sem nenhum warning.
Nomes começados com 1 sublinhado: _*
Nomes que começam com 1 sublinhado, quando são criados dentro de um módulo (ou pacote), não são importados quando a gente usa o comando:
from modulo import *
.
Quando criar um módulo que tenha alguma função, variável ou classe que você não queira que seja importada automaticamente, coloque o nome começando com 1 sublinhado. Exemplo: _funcao_interna()
.
Para deixar claro que o método ou variável são privados da classe, ou seja, não pode ser acessado fora dela, dê o nome ao método ou classe começando com 1 sublinhado.
Isso não os torna privados. É apenas uma convenção mesmo.
O encapsulamento existe no Python, mas ele não vai te proibir de tomar suas próprias decisões, por isso dizemos que é só uma convenção.
Nomes começados com 2 sublinhados: __*
Nomes começados com 2 sublinhados são métodos ou variáveis privados de uma classe.
Objetos externos não acessam uma propriedade ou método que comecem com sublinhado duplo __
class SecretString: # A not-at-all secure way to store a secret string.
def __init__(self, plain_string, pass_phrase):
self.__plain_string = plain_string
self.__pass_phrase = pass_phrase
def decrypt(self, pass_phrase): #Show string if the pass_phrase is correct.
if pass_phrase == self.__pass_phrase:
return self.__plain_string
else:
return ''
secret_string = SecretString("ACME: Top Secret", "antwerp")
print(secret_string.decrypt("antwerp"))
print(secret_string.__plain_text)
#Funciona !! … talvez não …
print(secret_string._SecretString__plain_string)
Dê um:
dir(secret_string)
Saída:
[‘_SecretString__pass_phrase’, ‘_SecretString__plain_string‘, ‘__class__’, ‘__delattr__’, ‘__dict__’, ‘__dir__’, ‘__doc__’, ‘__eq__’, ‘__format__’, ‘__ge__’, ‘__getattribute__’, ‘__gt__’, ‘__hash__’, ‘__init__’, ‘__init_subclass__’, ‘__le__’, ‘__lt__’, ‘__module__’, ‘__ne__’, ‘__new__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__setattr__’, ‘__sizeof__’, ‘__str__’, ‘__subclasshook__’, ‘__weakref__’, ‘decrypt’]
Quando criamos váriáveis e métodos com 2 sublinhados o python insere o nome da classe antes do nome da variável ou método que você criou.
Nome da classe: _SecretString
Nome da variável ou método: __plain_string
Herança básica
Nos permite criar relacionamento “é um(a)” entre duas ou mais classes, abstraindo detalhes comuns em superclasses e armazenando os específicos na subclasse.
Tecnicamente, todas as classes que criamos usam herança, todas as classes Python são subclasses de uma classe especial que se chama object.
class MySubClass(object):
pass
Variáveis de classe
class Contact:
all_contacts = []
def __init__(self, name, email):
self.name = name
self.email = email
Contact.all_contacts.append(self)
A lista all_contacts, como faz parte da definição da classe, é na verdade compartilhada por todas as instâncias dessa classe, mas, e se alguns dos nossos contatos também forem fornecedores?
Classe Supplier(fornecedor) age, isto é, se comporta como um contato também.
class Supplier(Contact):
def order(self, order):
print("Nós enviamos o pedido {} para o {}".format(order, self.name))
c = Contact("alguém qualquer", "somebody@example.net")
s = Supplier("fornecedor", "supplier@example.net")
print(c.name, c.email, s.name, s.email)
c.all_contacts
c.order("preciso de um alicate")
s.order("preciso de um alicate")
O contato não tem o atributo order, veja em laranja no código acima, isso vai gerar um erro de atributo.
O fornecedor pode fazer o que o contato pode fazer e mais tudo o que precisa como fornecedor.
Substituindo(Overriding) e Super
class Friend(Contact):
def __init__(self, name, email, phone):
self.name = name
self.email = email
self.phone = phone
class Friend(Contact):
def __init__(self, name, email, phone):
super().__init__(name, email)
self.phone = phone
Herança múltipla
Como regra geral, se você acha que precisa de herança múltipla, provavelmente você está errado, mas, se você sabe que precisa mesmo, provavelmente está certo.
class MailSender:
def send_mail(self, message):
print("Enviando o email para: " + self.email)
# Adicione a lógica de e-mail aqui
# Definindo uma nova classe que é um contato e um MailSender
class EmailableContact(Contact, MailSender):
pass
e = EmailableContact("TotiCavalcanti", "toti@example.net")
Contact.all_contacts
e.send_mail("Olá, teste de e-mail aqui")
Polimorfismo
Diferentes comportamentos acontecem dependendo de qual subclasse está sendo usada, sem ter que saber explicitamente o que a subclasse realmente é:
class AudioFile:
def __init__(self, filename):
if not filename.endswith(self.ext):
raise Exception("Formato inválido!")
self.filename = filename
class MP3File(AudioFile):
ext = "mp3"
def play(self):
print("Tocando {} como mp3".format(self.filename))
class WavFile(AudioFile):
ext = "wav"
def play(self):
print("Tocando {} como wav".format(self.filename))
class OggFile(AudioFile):
ext = "ogg"
def play(self):
print("Tocando {} como ogg".format(self.filename))
ogg = OggFile("myfile.ogg")
ogg.play()
mp3 = MP3File("myfile.mp3")
mp3.play()
not_an_mp3 = MP3File("myfile.ogg")
Duck Typing
Nos permite usar qualquer objeto que forneça o comportamento necessário sem forçá-lo a ser uma subclasse. O exemplo a seguir não estende o AudioFile, mas pode interagir com o Python usando exatamente a mesma interface:
class FlacFile:
def __init__(self, filename):
if not filename.endswith(".flac"):
raise Exception("Formato inválido!")
self.filename = filename
def play(self):
print("Tocando {} como flac".format(self.filename))